From 02c9ef4e3bce48bbb94f737b6fc88766ce04fca6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 09:15:35 -0800 Subject: [PATCH 01/94] added octoprint-tentacle.svg and file-gcode.svg, also made some small tweaks to a few other images --- docs/ButtonImages.html | 6 + styles/z-bolt/images/file-gcode.svg | 110 ++++++++++++ styles/z-bolt/images/file-stl.svg | 81 +++++---- styles/z-bolt/images/octoprint-tentacle.svg | 20 +++ styles/z-bolt/images/sd-eject.svg | 190 +++++--------------- styles/z-bolt/images/sd.svg | 135 +++----------- 6 files changed, 245 insertions(+), 297 deletions(-) create mode 100755 styles/z-bolt/images/file-gcode.svg create mode 100755 styles/z-bolt/images/octoprint-tentacle.svg mode change 100644 => 100755 styles/z-bolt/images/sd.svg diff --git a/docs/ButtonImages.html b/docs/ButtonImages.html index 14347991..50d98c8c 100755 --- a/docs/ButtonImages.html +++ b/docs/ButtonImages.html @@ -83,6 +83,9 @@
filament-spool
+ +
file-gcode
+
file-stl
@@ -182,6 +185,9 @@
nozzle
+ +
octoprint-tentacle
+
open
diff --git a/styles/z-bolt/images/file-gcode.svg b/styles/z-bolt/images/file-gcode.svg new file mode 100755 index 00000000..7ab38705 --- /dev/null +++ b/styles/z-bolt/images/file-gcode.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/file-stl.svg b/styles/z-bolt/images/file-stl.svg index 05319fdf..3c46aef6 100755 --- a/styles/z-bolt/images/file-stl.svg +++ b/styles/z-bolt/images/file-stl.svg @@ -3,44 +3,49 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/octoprint-tentacle.svg b/styles/z-bolt/images/octoprint-tentacle.svg new file mode 100755 index 00000000..4f4582e6 --- /dev/null +++ b/styles/z-bolt/images/octoprint-tentacle.svg @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/styles/z-bolt/images/sd-eject.svg b/styles/z-bolt/images/sd-eject.svg index 755e60be..61c8d493 100644 --- a/styles/z-bolt/images/sd-eject.svg +++ b/styles/z-bolt/images/sd-eject.svg @@ -1,149 +1,41 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/sd.svg b/styles/z-bolt/images/sd.svg old mode 100644 new mode 100755 index 356e5c1f..16e2b889 --- a/styles/z-bolt/images/sd.svg +++ b/styles/z-bolt/images/sd.svg @@ -1,110 +1,25 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + From 2294ca9b52e3370bf2afb18985c2333dd6c955ed Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 11:51:56 -0800 Subject: [PATCH 02/94] changed file image to file-gcode.svg --- ui/FilesPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 19140a3d..0c9bc561 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -156,7 +156,7 @@ func (this *filesPanel) addFile(box *gtk.Box, fileInformation *octoprint.FileInf file.SetMarginBottom(1) file.SetHExpand(true) - image := utils.MustImageFromFileWithSize("file-stl.svg", this.Scaled(35), this.Scaled(35)) + image := utils.MustImageFromFileWithSize("file-gcode.svg", this.Scaled(35), this.Scaled(35)) file.Add(image) file.Add(labels) From 70d03cf05a2613d1ad17da6100a4034f9247d5a0 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 11:52:44 -0800 Subject: [PATCH 03/94] changed file image to file-gcode.svg --- ui/PrintStatusPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/PrintStatusPanel.go b/ui/PrintStatusPanel.go index d52bf352..4a908d73 100755 --- a/ui/PrintStatusPanel.go +++ b/ui/PrintStatusPanel.go @@ -128,7 +128,7 @@ func (this *printStatusPanel) createProgressBar() *gtk.ProgressBar { } func (this *printStatusPanel) createInfoBox() *gtk.Box { - this.fileLabel = utils.MustLabelWithImage("file-stl.svg", "") + this.fileLabel = utils.MustLabelWithImage("file-gcode.svg", "") ctx, _ := this.fileLabel.GetStyleContext() ctx.AddClass("printing-status-label") From eb7a437bb0a34c4538ff93a796e54eb67c3e87b6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 12:18:45 -0800 Subject: [PATCH 04/94] added abilility to browse files on printer's SD card --- ui/FilesPanel.go | 354 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 257 insertions(+), 97 deletions(-) mode change 100755 => 100644 ui/FilesPanel.go diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go old mode 100755 new mode 100644 index 0c9bc561..33b2bf19 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -27,7 +27,7 @@ func FilesPanel( ) *filesPanel { if filesPanelInstance == nil { locationHistory := locationHistory { - locations: []octoprint.Location{octoprint.Local}, + locations: []octoprint.Location{}, } instance := &filesPanel { @@ -77,13 +77,13 @@ func (this *filesPanel) createRefreshButton() gtk.IWidget { } func (this *filesPanel) createBackButton() gtk.IWidget { - - // TODO: look into making a BackButton class - image := utils.MustImageFromFileWithSize("back.svg", this.Scaled(40), this.Scaled(40)) return utils.MustButton(image, func() { - if this.locationHistory.isRoot() { + if this.locationHistory.length() < 1 { this.UI.GoToPreviousPanel() + } else if this.locationHistory.isRoot() { + this.locationHistory.goBack() + this.doLoadFiles() } else { this.locationHistory.goBack() this.doLoadFiles() @@ -92,123 +92,188 @@ func (this *filesPanel) createBackButton() gtk.IWidget { } func (this *filesPanel) doLoadFiles() { + utils.EmptyTheContainer(&this.listBox.Container) + + sortedFiles := this.getSortedFiles() + if sortedFiles == nil { + this.addRootLocations() + } else { + this.addSortedFiles(sortedFiles) + } + + this.listBox.ShowAll() +} + +func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { var files []*octoprint.FileInformation - utils.Logger.Info("Loading list of files from: ", string(this.locationHistory.current())) + length := this.locationHistory.length() + if length < 1 { + return nil + } + + current := this.locationHistory.current() + utils.Logger.Info("Loading list of files from: ", string(current)) - filesRequest := &octoprint.FilesRequest{Location: this.locationHistory.current(), Recursive: false} + filesRequest := &octoprint.FilesRequest { + Location: current, + Recursive: false, + } filesResponse, err := filesRequest.Do(this.UI.Client) if err != nil { - utils.LogError("files.doLoadFiles()", "Do(FilesRequest)", err) + utils.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) files = []*octoprint.FileInformation{} } else { files = filesResponse.Files } - s := byDate(files) - sort.Sort(s) + sortedFiles := byDate(files) + sort.Sort(sortedFiles) - utils.EmptyTheContainer(&this.listBox.Container) + return sortedFiles +} + + +func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileInformation) { + var index int = 0 - for _, fileInformation := range s { + for _, fileInformation := range sortedFiles { if fileInformation.IsFolder() { - this.addFolder(this.listBox, fileInformation) + this.addItem(fileInformation, index) + index++ } } - for _, fileInformation := range s { + for _, fileInformation := range sortedFiles { if !fileInformation.IsFolder() { - this.addFile(this.listBox, fileInformation) + this.addItem(fileInformation, index) + index++ } } - - this.listBox.ShowAll() } -func (this *filesPanel) addFile(box *gtk.Box, fileInformation *octoprint.FileInformation) { - frame, _ := gtk.FrameNew("") - - name := utils.MustLabel(fileInformation.Name) - name.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(fileInformation.Name))) - name.SetHExpand(true) - name.SetHAlign(gtk.ALIGN_START) - - info := utils.MustLabel("") - info.SetHAlign(gtk.ALIGN_START) - info.SetMarkup(fmt.Sprintf("Uploaded: %s - Size: %s", - humanize.Time(fileInformation.Date.Time), humanize.Bytes(uint64(fileInformation.Size)), - )) - - labels := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labels.Add(name) - labels.Add(info) - labels.SetVExpand(true) - labels.SetVAlign(gtk.ALIGN_CENTER) - labels.SetHAlign(gtk.ALIGN_START) - - actions := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - actions.Add(this.createLoadAndPrintButton("print.svg", fileInformation)) - - file := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - file.SetMarginTop(1) - file.SetMarginEnd(15) - file.SetMarginStart(15) - file.SetMarginBottom(1) - file.SetHExpand(true) - - image := utils.MustImageFromFileWithSize("file-gcode.svg", this.Scaled(35), this.Scaled(35)) - file.Add(image) - - file.Add(labels) - file.Add(actions) - - frame.Add(file) - box.Add(frame) -} -func (this *filesPanel) addFolder(box *gtk.Box, fileInformation *octoprint.FileInformation) { - frame, _ := gtk.FrameNew("") +func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, index int) { + isFolder := fileInformation.IsFolder() - labels := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - nameLabel := utils.MustLabel(fileInformation.Name) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(fileInformation.Name))) + var itemImage *gtk.Image + if isFolder { + itemImage = utils.MustImageFromFileWithSize("folder.svg", this.Scaled(35), this.Scaled(35)) + } else { + itemImage = utils.MustImageFromFileWithSize("file-gcode.svg", this.Scaled(35), this.Scaled(35)) + } + topBox.Add(itemImage) + + + + + name := fileInformation.Name + nameLabel := utils.MustLabel(name) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) nameLabel.SetHExpand(true) nameLabel.SetHAlign(gtk.ALIGN_START) - labels.Add(nameLabel) - info := utils.MustLabel("") - info.SetHAlign(gtk.ALIGN_START) - info.SetMarkup(fmt.Sprintf("Size: %s", - humanize.Bytes(uint64(fileInformation.Size)), - )) - labels.Add(info) + infoLabel := utils.MustLabel("") + infoLabel.SetHAlign(gtk.ALIGN_START) + if isFolder { + infoLabel.SetMarkup(fmt.Sprintf("Size: %s", + humanize.Bytes(uint64(fileInformation.Size)), + )) + } else { + infoLabel.SetMarkup(fmt.Sprintf("Uploaded: %s - Size: %s", + humanize.Time(fileInformation.Date.Time), humanize.Bytes(uint64(fileInformation.Size)), + )) + } - labels.SetVExpand(true) - labels.SetVAlign(gtk.ALIGN_CENTER) - labels.SetHAlign(gtk.ALIGN_START) + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + labelsBox.Add(nameLabel) + labelsBox.Add(infoLabel) + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") - actionsBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - actionsBox.Add(this.createOpenFolderButton(fileInformation)) + topBox.Add(labelsBox) + + + + + var itemButton *gtk.Button + if isFolder { + itemButton = this.createOpenFolderButton(fileInformation) + } else { + itemButton = this.createLoadAndPrintButton("print.svg", fileInformation) + } + + actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + actionBox.Add(itemButton) + topBox.Add(actionBox) + + + + + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + listItemBox.Add(topBox) + + + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) + + + + itemButtonStyleContext, _ := itemButton.GetStyleContext() + listItemBoxStyleContext, _:= listItemBox.GetStyleContext() + listItemFrameStyleContext, _ := listItemFrame.GetStyleContext() + if index % 2 != 0 { + itemButtonStyleContext.AddClass("list-item-nth-child-even") + listItemBoxStyleContext.AddClass("list-item-nth-child-even") + listItemFrameStyleContext.AddClass("list-item-nth-child-even") + } + + this.listBox.Add(listItemFrame) +} + + +func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *gtk.Button { + image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) + button := utils.MustButton(image, func() { + this.locationHistory = locationHistory { + locations: []octoprint.Location{location}, + } + + this.doLoadFiles() + }) + + ctx, _ := button.GetStyleContext() + ctx.AddClass("color1") + ctx.AddClass("file-list") - fileBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - fileBox.SetMarginTop(1) - fileBox.SetMarginEnd(15) - fileBox.SetMarginStart(15) - fileBox.SetMarginBottom(1) - fileBox.SetHExpand(true) + return button +} - image := utils.MustImageFromFileWithSize("folder.svg", this.Scaled(35), this.Scaled(35)) - fileBox.Add(image) +func (this *filesPanel) createOpenFolderButton(fileInformation *octoprint.FileInformation) *gtk.Button { + image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) + button := utils.MustButton(image, func() { + this.locationHistory.goForward(fileInformation.Name) + this.doLoadFiles() + }) - fileBox.Add(labels) - fileBox.Add(actionsBox) + ctx, _ := button.GetStyleContext() + ctx.AddClass("color1") + ctx.AddClass("file-list") - frame.Add(fileBox) - box.Add(frame) + return button } -func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInformation *octoprint.FileInformation) gtk.IWidget { +func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInformation *octoprint.FileInformation) *gtk.Button { button := utils.MustButton( utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { @@ -232,20 +297,115 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInfor return button } -func (this *filesPanel) createOpenFolderButton(fileInformation *octoprint.FileInformation) gtk.IWidget { - image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) - button := utils.MustButton(image, func() { - this.locationHistory.goForward(fileInformation.Name) - this.doLoadFiles() - }) +func (this *filesPanel) addRootLocations() { + this.addMessage("Select source location:") + this.addRootLocation(octoprint.Local, 0) + this.addRootLocation(octoprint.SDCard, 1) +} - ctx, _ := button.GetStyleContext() - ctx.AddClass("color1") - ctx.AddClass("file-list") +func (this *filesPanel) addMessage(message string) { + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + nameLabel := utils.MustLabel(message) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) + nameLabel.SetHExpand(true) + nameLabel.SetHAlign(gtk.ALIGN_START) - return button + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + labelsBox.Add(nameLabel) + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") + + topBox.Add(labelsBox) + + + + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + listItemBox.Add(topBox) + + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) + + + this.listBox.Add(listItemFrame) } + +func (this *filesPanel) addRootLocation(location octoprint.Location, index int) { + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + + var itemImage *gtk.Image + if location == octoprint.Local { + itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) + } else { + itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) + } + topBox.Add(itemImage) + + + name := "" + if location == octoprint.Local { + name = " OctoPrint" + } else { + name = " SD Card" + } + nameLabel := utils.MustLabel(name) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) + nameLabel.SetHExpand(true) + nameLabel.SetHAlign(gtk.ALIGN_START) + + infoLabel := utils.MustLabel("") + infoLabel.SetHAlign(gtk.ALIGN_START) + infoLabel.SetMarkup(" ") + + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + labelsBox.Add(nameLabel) + labelsBox.Add(infoLabel) + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") + + topBox.Add(labelsBox) + + + var itemButton *gtk.Button + if location == octoprint.Local { + itemButton = this.createOpenLocationButton(location) + } else { + itemButton = this.createOpenLocationButton(location) + } + + actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + actionBox.Add(itemButton) + topBox.Add(actionBox) + + + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + listItemBox.Add(topBox) + + + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) + + this.listBox.Add(listItemFrame) +} + + + /* func (this *filesPanel) isReady() bool { state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client) From 28929f1a301c86e95d294827aed3ecc6c094390f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 12:39:35 -0800 Subject: [PATCH 05/94] moved LocationHistory.go from ui to utils --- {ui => utils}/LocationHistory.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {ui => utils}/LocationHistory.go (100%) diff --git a/ui/LocationHistory.go b/utils/LocationHistory.go similarity index 100% rename from ui/LocationHistory.go rename to utils/LocationHistory.go From 14c6989b9f8b80b8b5860fbec625d555693dfc71 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 12:40:09 -0800 Subject: [PATCH 06/94] moved LocationHistory.go from ui to utils --- ui/FilesPanel.go | 26 +++++++++++++------------- utils/LocationHistory.go | 38 +++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 30 deletions(-) mode change 100644 => 100755 ui/FilesPanel.go diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go old mode 100644 new mode 100755 index 33b2bf19..3795b4a1 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -18,7 +18,7 @@ type filesPanel struct { CommonPanel listBox *gtk.Box - locationHistory locationHistory + locationHistory utils.LocationHistory } func FilesPanel( @@ -26,8 +26,8 @@ func FilesPanel( parentPanel interfaces.IPanel, ) *filesPanel { if filesPanelInstance == nil { - locationHistory := locationHistory { - locations: []octoprint.Location{}, + locationHistory := utils.LocationHistory { + Locations: []octoprint.Location{}, } instance := &filesPanel { @@ -79,13 +79,13 @@ func (this *filesPanel) createRefreshButton() gtk.IWidget { func (this *filesPanel) createBackButton() gtk.IWidget { image := utils.MustImageFromFileWithSize("back.svg", this.Scaled(40), this.Scaled(40)) return utils.MustButton(image, func() { - if this.locationHistory.length() < 1 { + if this.locationHistory.Length() < 1 { this.UI.GoToPreviousPanel() - } else if this.locationHistory.isRoot() { - this.locationHistory.goBack() + } else if this.locationHistory.IsRoot() { + this.locationHistory.GoBack() this.doLoadFiles() } else { - this.locationHistory.goBack() + this.locationHistory.GoBack() this.doLoadFiles() } }) @@ -107,12 +107,12 @@ func (this *filesPanel) doLoadFiles() { func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { var files []*octoprint.FileInformation - length := this.locationHistory.length() + length := this.locationHistory.Length() if length < 1 { return nil } - current := this.locationHistory.current() + current := this.locationHistory.CurrentLocation() utils.Logger.Info("Loading list of files from: ", string(current)) filesRequest := &octoprint.FilesRequest { @@ -127,7 +127,7 @@ func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { files = filesResponse.Files } - sortedFiles := byDate(files) + sortedFiles := utils.FileInformationsByDate(files) sort.Sort(sortedFiles) return sortedFiles @@ -245,8 +245,8 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { - this.locationHistory = locationHistory { - locations: []octoprint.Location{location}, + this.locationHistory = utils.LocationHistory { + Locations: []octoprint.Location{location}, } this.doLoadFiles() @@ -262,7 +262,7 @@ func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *g func (this *filesPanel) createOpenFolderButton(fileInformation *octoprint.FileInformation) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { - this.locationHistory.goForward(fileInformation.Name) + this.locationHistory.GoForward(fileInformation.Name) this.doLoadFiles() }) diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go index a0a6e676..d2cc0fc4 100755 --- a/utils/LocationHistory.go +++ b/utils/LocationHistory.go @@ -1,38 +1,42 @@ -package ui +package utils import ( // "fmt" // "sort" "github.com/mcuadros/go-octoprint" + // "github.com/mcuadros/go-octoprint/apis" // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) -type byDate []*octoprint.FileInformation - -func (s byDate) Len() int { return len(s) } -func (s byDate) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s byDate) Less(i, j int) bool { return s[j].Date.Time.Before(s[i].Date.Time) } +type LocationHistory struct { + Locations []octoprint.Location +} -type locationHistory struct { - locations []octoprint.Location +func (this *LocationHistory) Length() int { + return len(this.Locations) } -func (l *locationHistory) current() octoprint.Location { - return l.locations[len(l.locations) - 1] +func (this *LocationHistory) CurrentLocation() octoprint.Location { + length := this.Length() + if length < 1 { + panic("LocationHistory.current() - locations is empty") + } + + return this.Locations[length - 1] } -func (l *locationHistory) goForward(folder string) { - newLocation := string(l.current()) + "/" + folder - l.locations = append(l.locations, octoprint.Location(newLocation)) +func (this *LocationHistory) GoForward(folder string) { + newLocation := string(this.CurrentLocation()) + "/" + folder + this.Locations = append(this.Locations, octoprint.Location(newLocation)) } -func (l *locationHistory) goBack() { - l.locations = l.locations[0 : len(l.locations) - 1] +func (this *LocationHistory) GoBack() { + this.Locations = this.Locations[0 : len(this.Locations) - 1] } -func (l *locationHistory) isRoot() bool { - if len(l.locations) > 1 { +func (this *LocationHistory) IsRoot() bool { + if len(this.Locations) > 1 { return false } else { return true From ac5b0b9d23c70ec5ec728a377c0cead5a6926497 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 12:40:40 -0800 Subject: [PATCH 07/94] moved FileInformationsByDate into its own file --- utils/FileInformationsByDate.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 utils/FileInformationsByDate.go diff --git a/utils/FileInformationsByDate.go b/utils/FileInformationsByDate.go new file mode 100755 index 00000000..c2ca83aa --- /dev/null +++ b/utils/FileInformationsByDate.go @@ -0,0 +1,24 @@ +package utils + +import ( + // "fmt" + // "sort" + + "github.com/mcuadros/go-octoprint" + // "github.com/mcuadros/go-octoprint/apis" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" +) + +type FileInformationsByDate []*octoprint.FileInformation + +func (this FileInformationsByDate) Len() int { + return len(this) +} + +func (this FileInformationsByDate) Swap(i, j int) { + this[i], this[j] = this[j], this[i] +} + +func (this FileInformationsByDate) Less(i, j int) bool { + return this[j].Date.Time.Before(this[i].Date.Time) +} From fb4bf8be88dfddb5d5b1ba71baaad7981a2fc3b6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 19:40:55 -0800 Subject: [PATCH 08/94] added ability to browse and print files from SD card --- ui/FilesPanel.go | 224 ++++++++++++++++++++++-------------------- utils/string_utils.go | 21 +++- 2 files changed, 136 insertions(+), 109 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 3795b4a1..22b30647 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -3,6 +3,7 @@ package ui import ( "fmt" "sort" + "strings" "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" @@ -127,12 +128,125 @@ func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { files = filesResponse.Files } - sortedFiles := utils.FileInformationsByDate(files) + var filteredFiles []*octoprint.FileInformation + for i := range files { + if !strings.HasPrefix(files[i].Path, "trash") { + filteredFiles = append(filteredFiles, files[i]) + } + } + + sortedFiles := utils.FileInformationsByDate(filteredFiles) + // sortedFiles := utils.FileInformationsByName(filteredFiles) sort.Sort(sortedFiles) return sortedFiles } +func (this *filesPanel) addRootLocations() { + this.addMessage("Select source location:") + this.addRootLocation(octoprint.Local, 0) + this.addRootLocation(octoprint.SDCard, 1) +} + +func (this *filesPanel) addMessage(message string) { + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + nameLabel := utils.MustLabel(message) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) + nameLabel.SetHExpand(true) + nameLabel.SetHAlign(gtk.ALIGN_START) + + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + labelsBox.Add(nameLabel) + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") + + topBox.Add(labelsBox) + + + + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + listItemBox.Add(topBox) + + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) + + + this.listBox.Add(listItemFrame) +} + +func (this *filesPanel) addRootLocation(location octoprint.Location, index int) { + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + + var itemImage *gtk.Image + if location == octoprint.Local { + itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) + } else { + itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) + } + topBox.Add(itemImage) + + + name := "" + if location == octoprint.Local { + name = " OctoPrint" + } else { + name = " SD Card" + } + nameLabel := utils.MustLabel(name) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) + nameLabel.SetHExpand(true) + nameLabel.SetHAlign(gtk.ALIGN_START) + + infoLabel := utils.MustLabel("") + infoLabel.SetHAlign(gtk.ALIGN_START) + infoLabel.SetMarkup(" ") + + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + labelsBox.Add(nameLabel) + labelsBox.Add(infoLabel) + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") + + topBox.Add(labelsBox) + + + var itemButton *gtk.Button + if location == octoprint.Local { + itemButton = this.createOpenLocationButton(location) + } else { + itemButton = this.createOpenLocationButton(location) + } + + actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + actionBox.Add(itemButton) + topBox.Add(actionBox) + + + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + listItemBox.Add(topBox) + + + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) + + this.listBox.Add(listItemFrame) +} func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileInformation) { var index int = 0 @@ -171,7 +285,7 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde name := fileInformation.Name nameLabel := utils.MustLabel(name) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) nameLabel.SetHExpand(true) nameLabel.SetHAlign(gtk.ALIGN_START) @@ -297,112 +411,6 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInfor return button } -func (this *filesPanel) addRootLocations() { - this.addMessage("Select source location:") - this.addRootLocation(octoprint.Local, 0) - this.addRootLocation(octoprint.SDCard, 1) -} - -func (this *filesPanel) addMessage(message string) { - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - nameLabel := utils.MustLabel(message) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) - nameLabel.SetHExpand(true) - nameLabel.SetHAlign(gtk.ALIGN_START) - - labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labelsBox.Add(nameLabel) - labelsBox.SetVExpand(false) - labelsBox.SetVAlign(gtk.ALIGN_CENTER) - labelsBox.SetHAlign(gtk.ALIGN_START) - labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - labelsBoxStyleContext.AddClass("labels-box") - - topBox.Add(labelsBox) - - - - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) - listItemBox.Add(topBox) - - listItemFrame, _ := gtk.FrameNew("") - listItemFrame.Add(listItemBox) - - - this.listBox.Add(listItemFrame) -} - - -func (this *filesPanel) addRootLocation(location octoprint.Location, index int) { - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - - var itemImage *gtk.Image - if location == octoprint.Local { - itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) - } else { - itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) - } - topBox.Add(itemImage) - - - name := "" - if location == octoprint.Local { - name = " OctoPrint" - } else { - name = " SD Card" - } - nameLabel := utils.MustLabel(name) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) - nameLabel.SetHExpand(true) - nameLabel.SetHAlign(gtk.ALIGN_START) - - infoLabel := utils.MustLabel("") - infoLabel.SetHAlign(gtk.ALIGN_START) - infoLabel.SetMarkup(" ") - - labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labelsBox.Add(nameLabel) - labelsBox.Add(infoLabel) - labelsBox.SetVExpand(false) - labelsBox.SetVAlign(gtk.ALIGN_CENTER) - labelsBox.SetHAlign(gtk.ALIGN_START) - labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - labelsBoxStyleContext.AddClass("labels-box") - - topBox.Add(labelsBox) - - - var itemButton *gtk.Button - if location == octoprint.Local { - itemButton = this.createOpenLocationButton(location) - } else { - itemButton = this.createOpenLocationButton(location) - } - - actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - actionBox.Add(itemButton) - topBox.Add(actionBox) - - - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) - listItemBox.Add(topBox) - - - listItemFrame, _ := gtk.FrameNew("") - listItemFrame.Add(listItemBox) - - this.listBox.Add(listItemFrame) -} diff --git a/utils/string_utils.go b/utils/string_utils.go index 012559c4..a673511e 100755 --- a/utils/string_utils.go +++ b/utils/string_utils.go @@ -35,10 +35,12 @@ func ReplaceHTMLTag(html, from, to string) string { return html } +// TODO: Clean up StrEllipsis(), StrEllipsisLen(), and TruncateString() and consolidate +// into a single function. func StrEllipsis(name string) string { l := len(name) if l > 32 { - return name[:12] + "..." + name[l-17:l] + return name[:12] + "..." + name[l - 17:l] } return name @@ -52,3 +54,20 @@ func StrEllipsisLen(name string, length int) string { return name } + +func TruncateString(str string, length int) string { + if length < 3 { + length = 3 + } + + truncateString := str + if len(str) > length { + if length > 3 { + length -= 3 + } + + truncateString = str[0:length] + "..." + } + + return truncateString +} From 67c96c693b0b5c18b75ee68fddcc24e4da3cd653 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 20:04:03 -0800 Subject: [PATCH 09/94] added CSS to display different background colors for alternating list items --- styles/z-bolt/style.css | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css index 461b055e..fa6d3d24 100755 --- a/styles/z-bolt/style.css +++ b/styles/z-bolt/style.css @@ -36,6 +36,21 @@ progress { } +/* File browser *********************************************************** */ +.list-item-nth-child-even { + background-color: #34383C; +} + +.labels-box { + margin-top: 10px; +} + +.preview-image-list-item { + margin-left: 76px; + margin-bottom: 15px; +} + + /* Button styles *********************************************************** */ @@ -109,6 +124,7 @@ button.file-list { margin: 0px; } + entry { font-size: 30px; background-color: #20292F; From ac447f2743afe5a4eb178046df669e84ffbe1e3f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 21:13:07 -0800 Subject: [PATCH 10/94] Break up the Momolith! - separated FileRequest and FileInformation out from common.go --- .../mcuadros/go-octoprint/FileRequest.go | 133 ++++++++++++++++++ .../mcuadros/go-octoprint/common.go | 86 +++++------ .../github.com/mcuadros/go-octoprint/files.go | 58 ++++---- 3 files changed, 210 insertions(+), 67 deletions(-) create mode 100755 vendor/github.com/mcuadros/go-octoprint/FileRequest.go mode change 100644 => 100755 vendor/github.com/mcuadros/go-octoprint/files.go diff --git a/vendor/github.com/mcuadros/go-octoprint/FileRequest.go b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go new file mode 100755 index 00000000..7ac440b4 --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go @@ -0,0 +1,133 @@ +//package apis +package octoprint + +import ( + "fmt" + "encoding/json" + + // "log" + // "strconv" + // "strings" + // "time" + + // "../octoprint" + //"github.com/mcuadros/go-octoprint" +) + +// Retrieve a specific file’s or folder’s information +// GET /api/files/(string:location)/(path:filename) +// https://docs.octoprint.org/en/master/api/files.html#retrieve-a-specific-file-s-or-folder-s-information + + +// FileRequest retrieves the selected file’s or folder’s information. +type FileRequest struct { + // Location of the file for which to retrieve the information/ Can be either + // `local` or `sdcard`. + Location Location + + // Filename of the file for which to retrieve the information. + Filename string + + // Recursive if set to true, return all files and folders recursively. + // Otherwise only return items on same level. + Recursive bool +} + +// FileInformation contains information regarding a file. +// https://docs.octoprint.org/en/master/api/datamodel.html#file-information +type FileInformation struct { + // Name is name of the file without path. E.g. “file.gco” for a file + // “file.gco” located anywhere in the file system. + Name string `json:"name"` + + // The name of the file without the path. + Display string `json:"display"` + + // Path is the path to the file within the location. E.g. + //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” + // and “subfolder” relative to the root of the location. + Path string `json:"path"` + + // Type of file. model or machinecode. Or folder if it’s a folder, in + // which case the children node will be populated. + Type string `json:"type"` + + // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` + // for .stl files, or `["machinecode", "gcode"]` for .gcode files. + // `["folder"]` for folders. + TypePath []string `json:"typePath"` + + + + + // Additional properties depend on type. For a type value of folder, see Folders. For any other value see Files. + + // * Folders + // --children + // --size + + + + // * Files + // Hash is the MD5 hash of the file. Only available for `local` files. + Hash string `json:"hash"` + + // Size of the file in bytes. Only available for `local` files or `sdcard` + // files if the printer supports file sizes for sd card files. + Size uint64 `json:"size"` + + // Date when this file was uploaded. Only available for `local` files. + Date JSONTime `json:"date"` + + // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, + // `sdcard` when stored on the printer’s SD card (if available). + Origin string `json:"origin"` + + // Refs references relevant to this file, left out in abridged version. + Refs Reference `json:"refs"` + + // GCodeAnalysis information from the analysis of the GCODE file, if + // available. Left out in abridged version. + GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` + + + + + // * Additional properties not listed in the SDK... + + // Print information from the print stats of a file. + Print PrintStats `json:"print"` + + + // Relative path to the preview thumbnail image (if it exists) + // The PrusaSlicer Thumbnails plug-in is required or this. + Thumbnail string `json:"thumbnail"` +} + +// IsFolder it returns true if the file is a folder. +func (f *FileInformation) IsFolder() bool { + if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { + return true + } + + return false +} + +// Do sends an API request and returns the API response +func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { + uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, + cmd.Location, cmd.Filename, cmd.Recursive, + ) + + b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) + if err != nil { + return nil, err + } + + r := &FileInformation{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/vendor/github.com/mcuadros/go-octoprint/common.go b/vendor/github.com/mcuadros/go-octoprint/common.go index 603b9bcf..10df312e 100755 --- a/vendor/github.com/mcuadros/go-octoprint/common.go +++ b/vendor/github.com/mcuadros/go-octoprint/common.go @@ -281,62 +281,64 @@ type FilesResponse struct { Free uint64 } +// FileInformation is now in FileRequest.go +// TODO: remove this commented code // FileInformation contains information regarding a file. -type FileInformation struct { - // Name is name of the file without path. E.g. “file.gco” for a file - // “file.gco” located anywhere in the file system. - Name string `json:"name"` +// type FileInformation struct { +// // Name is name of the file without path. E.g. “file.gco” for a file +// // “file.gco” located anywhere in the file system. +// Name string `json:"name"` - // The name of the file without the path - Display string `json:"display"` +// // The name of the file without the path +// Display string `json:"display"` - // Path is the path to the file within the location. E.g. - //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” - // and “subfolder” relative to the root of the location. - Path string `json:"path"` +// // Path is the path to the file within the location. E.g. +// //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” +// // and “subfolder” relative to the root of the location. +// Path string `json:"path"` - // Type of file. model or machinecode. Or folder if it’s a folder, in - // which case the children node will be populated. - Type string `json:"type"` +// // Type of file. model or machinecode. Or folder if it’s a folder, in +// // which case the children node will be populated. +// Type string `json:"type"` - // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` - // for .stl files, or `["machinecode", "gcode"]` for .gcode files. - // `["folder"]` for folders. - TypePath []string `json:"typePath"` +// // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` +// // for .stl files, or `["machinecode", "gcode"]` for .gcode files. +// // `["folder"]` for folders. +// TypePath []string `json:"typePath"` - // Hash is the MD5 hash of the file. Only available for `local` files. - Hash string `json:"hash"` +// // Hash is the MD5 hash of the file. Only available for `local` files. +// Hash string `json:"hash"` - // Size of the file in bytes. Only available for `local` files or `sdcard` - // files if the printer supports file sizes for sd card files. - Size uint64 `json:"size"` +// // Size of the file in bytes. Only available for `local` files or `sdcard` +// // files if the printer supports file sizes for sd card files. +// Size uint64 `json:"size"` - // Date when this file was uploaded. Only available for `local` files. - Date JSONTime `json:"date"` +// // Date when this file was uploaded. Only available for `local` files. +// Date JSONTime `json:"date"` - // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, - // `sdcard` when stored on the printer’s SD card (if available) - Origin string `json:"origin"` +// // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, +// // `sdcard` when stored on the printer’s SD card (if available) +// Origin string `json:"origin"` - // Refs references relevant to this file, left out in abridged versio - Refs Reference `json:"refs"` +// // Refs references relevant to this file, left out in abridged versio +// Refs Reference `json:"refs"` - // GCodeAnalysis information from the analysis of the GCODE file, if - // available. Left out in abridged version. - GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` +// // GCodeAnalysis information from the analysis of the GCODE file, if +// // available. Left out in abridged version. +// GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` - // Print information from the print stats of a file. - Print PrintStats `json:"print"` -} +// // Print information from the print stats of a file. +// Print PrintStats `json:"print"` +// } -// IsFolder it returns true if the file is a folder. -func (f *FileInformation) IsFolder() bool { - if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { - return true - } +// // IsFolder it returns true if the file is a folder. +// func (f *FileInformation) IsFolder() bool { +// if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { +// return true +// } - return false -} +// return false +// } // Reference of a file. type Reference struct { diff --git a/vendor/github.com/mcuadros/go-octoprint/files.go b/vendor/github.com/mcuadros/go-octoprint/files.go old mode 100644 new mode 100755 index fa3b789a..85063946 --- a/vendor/github.com/mcuadros/go-octoprint/files.go +++ b/vendor/github.com/mcuadros/go-octoprint/files.go @@ -40,36 +40,44 @@ var ( } ) +// FileRequest is now in FileRequest.go +// TODO: remove this commented code // FileRequest retrieves the selected file’s or folder’s information. -type FileRequest struct { - // Location of the file for which to retrieve the information, either - // `local` or `sdcard`. - Location Location - // Filename of the file for which to retrieve the information - Filename string - // Recursive if set to true, return all files and folders recursively. - // Otherwise only return items on same level. - Recursive bool -} +// type FileRequest struct { +// // Location of the file for which to retrieve the information, either +// // `local` or `sdcard`. +// Location Location + +// // Filename of the file for which to retrieve the information +// Filename string + +// // Recursive if set to true, return all files and folders recursively. +// // Otherwise only return items on same level. +// Recursive bool +// } + +// // Do sends an API request and returns the API response +// func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { +// uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, +// cmd.Location, cmd.Filename, cmd.Recursive, +// ) + +// b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) +// if err != nil { +// return nil, err +// } + +// r := &FileInformation{} +// if err := json.Unmarshal(b, r); err != nil { +// return nil, err +// } + +// return r, err +// } -// Do sends an API request and returns the API response -func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { - uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, - cmd.Location, cmd.Filename, cmd.Recursive, - ) - b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) - if err != nil { - return nil, err - } - r := &FileInformation{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - return r, err -} // FilesRequest retrieve information regarding all files currently available and // regarding the disk space still available locally in the system. From d59a1960572cace4b5a6a77909a284a510406eea Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 21:17:33 -0800 Subject: [PATCH 11/94] added thumbnail preview to file browser --- ui/FilesPanel.go | 38 ++++++++++++++++++++++++++++++ utils/FileInformationByName.go | 25 ++++++++++++++++++++ utils/gtk.go | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100755 utils/FileInformationByName.go diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 22b30647..84e4ceac 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -2,6 +2,7 @@ package ui import ( "fmt" + "os" "sort" "strings" @@ -338,6 +339,43 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde listItemBox.Add(topBox) + + + + + + + if !isFolder { + if fileInformation.Thumbnail != "" { + thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileInformation.Thumbnail) + utils.Logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) + + previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) + if imageFromUrlErr == nil { + utils.Logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it............") + + previewImageStyleContext, _ := previewImage.GetStyleContext() + previewImageStyleContext.AddClass("preview-image-list-item") + + bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) + bottomBox.Add(previewImage) + listItemBox.Add(bottomBox) + } + } + } + + + + + + + + + + + + + listItemFrame, _ := gtk.FrameNew("") listItemFrame.Add(listItemBox) diff --git a/utils/FileInformationByName.go b/utils/FileInformationByName.go new file mode 100755 index 00000000..cad5a71e --- /dev/null +++ b/utils/FileInformationByName.go @@ -0,0 +1,25 @@ +package utils + +import ( + // "fmt" + // "sort" + // "strings" + + "github.com/mcuadros/go-octoprint" + // "github.com/mcuadros/go-octoprint/apis" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" +) + +type FileInformationsByName []*octoprint.FileInformation + +func (this FileInformationsByName) Len() int { + return len(this) +} + +func (this FileInformationsByName) Swap(i, j int) { + this[i], this[j] = this[j], this[i] +} + +func (this FileInformationsByName) Less(i, j int) bool { + return this[j].Name > this[i].Name +} diff --git a/utils/gtk.go b/utils/gtk.go index 797851e9..e813352d 100755 --- a/utils/gtk.go +++ b/utils/gtk.go @@ -1,7 +1,10 @@ package utils import ( + "bytes" + "errors" "fmt" + "net/http" "path/filepath" "github.com/gotk3/gotk3/gdk" @@ -238,6 +241,46 @@ func MustImageFromFile(imageFileName string) *gtk.Image { return image } +func ImageFromUrl(imageUrl string) (*gtk.Image, error) { + if imageUrl == "" { + Logger.Error("MustImageFromUrl() - imageUrl is empty") + return nil, errors.New("imageUrl is empty") + } + + response, getErr:= http.Get(imageUrl) + if getErr != nil { + return nil, getErr + } + defer response.Body.Close() + + buf := new(bytes.Buffer) + readLength, readErr := buf.ReadFrom(response.Body) + if readErr != nil { + return nil, readErr + } else if readLength < 1 { + return nil, errors.New("bytes read was zero") + } + + pixbufLoader, newPixbufLoaderErr := gdk.PixbufLoaderNew() + if newPixbufLoaderErr != nil { + return nil, newPixbufLoaderErr + } + defer pixbufLoader.Close() + + writeLength, writeErr := pixbufLoader.Write(buf.Bytes()) + if writeErr != nil { + return nil, writeErr + } else if writeLength < 1 { + return nil, errors.New("bytes written was zero") + } + + pixbuf, _ := pixbufLoader.GetPixbuf() + image, imageNewFromPixbufErr := gtk.ImageNewFromPixbuf(pixbuf) + + return image, imageNewFromPixbufErr +} + + // MustCSSProviderFromFile returns a new gtk.CssProvider for a given css file, if error panics. func MustCSSProviderFromFile(css string) *gtk.CssProvider { p, err := gtk.CssProviderNew() From 212489706a86fe8a5dead116b836548bbaeec9cf Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 21:34:46 -0800 Subject: [PATCH 12/94] renamed FileInformation to FileResponse --- ui/FilesPanel.go | 54 +++++++++---------- ...ByDate.go => FileResponsesSortedByDate.go} | 8 +-- ...ByName.go => FileResponsesSortedByName.go} | 8 +-- .../mcuadros/go-octoprint/FileRequest.go | 25 +++++---- .../mcuadros/go-octoprint/common.go | 12 ++--- 5 files changed, 55 insertions(+), 52 deletions(-) rename utils/{FileInformationsByDate.go => FileResponsesSortedByDate.go} (56%) rename utils/{FileInformationByName.go => FileResponsesSortedByName.go} (56%) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 84e4ceac..3cef5214 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -106,8 +106,8 @@ func (this *filesPanel) doLoadFiles() { this.listBox.ShowAll() } -func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { - var files []*octoprint.FileInformation +func (this *filesPanel) getSortedFiles() []*octoprint.FileResponse { + var files []*octoprint.FileResponse length := this.locationHistory.Length() if length < 1 { @@ -124,20 +124,20 @@ func (this *filesPanel) getSortedFiles() []*octoprint.FileInformation { filesResponse, err := filesRequest.Do(this.UI.Client) if err != nil { utils.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) - files = []*octoprint.FileInformation{} + files = []*octoprint.FileResponse{} } else { files = filesResponse.Files } - var filteredFiles []*octoprint.FileInformation + var filteredFiles []*octoprint.FileResponse for i := range files { if !strings.HasPrefix(files[i].Path, "trash") { filteredFiles = append(filteredFiles, files[i]) } } - sortedFiles := utils.FileInformationsByDate(filteredFiles) - // sortedFiles := utils.FileInformationsByName(filteredFiles) + sortedFiles := utils.FileResponsesSortedByDate(filteredFiles) + // sortedFiles := utils.FileResponsesSortedByName(filteredFiles) sort.Sort(sortedFiles) return sortedFiles @@ -249,27 +249,27 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) this.listBox.Add(listItemFrame) } -func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileInformation) { +func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileResponse) { var index int = 0 - for _, fileInformation := range sortedFiles { - if fileInformation.IsFolder() { - this.addItem(fileInformation, index) + for _, fileResponse := range sortedFiles { + if fileResponse.IsFolder() { + this.addItem(fileResponse, index) index++ } } - for _, fileInformation := range sortedFiles { - if !fileInformation.IsFolder() { - this.addItem(fileInformation, index) + for _, fileResponse := range sortedFiles { + if !fileResponse.IsFolder() { + this.addItem(fileResponse, index) index++ } } } -func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, index int) { - isFolder := fileInformation.IsFolder() +func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) { + isFolder := fileResponse.IsFolder() topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) @@ -284,7 +284,7 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde - name := fileInformation.Name + name := fileResponse.Name nameLabel := utils.MustLabel(name) nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) nameLabel.SetHExpand(true) @@ -294,11 +294,11 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde infoLabel.SetHAlign(gtk.ALIGN_START) if isFolder { infoLabel.SetMarkup(fmt.Sprintf("Size: %s", - humanize.Bytes(uint64(fileInformation.Size)), + humanize.Bytes(uint64(fileResponse.Size)), )) } else { infoLabel.SetMarkup(fmt.Sprintf("Uploaded: %s - Size: %s", - humanize.Time(fileInformation.Date.Time), humanize.Bytes(uint64(fileInformation.Size)), + humanize.Time(fileResponse.Date.Time), humanize.Bytes(uint64(fileResponse.Size)), )) } @@ -318,9 +318,9 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde var itemButton *gtk.Button if isFolder { - itemButton = this.createOpenFolderButton(fileInformation) + itemButton = this.createOpenFolderButton(fileResponse) } else { - itemButton = this.createLoadAndPrintButton("print.svg", fileInformation) + itemButton = this.createLoadAndPrintButton("print.svg", fileResponse) } actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) @@ -346,8 +346,8 @@ func (this *filesPanel) addItem(fileInformation *octoprint.FileInformation, inde if !isFolder { - if fileInformation.Thumbnail != "" { - thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileInformation.Thumbnail) + if fileResponse.Thumbnail != "" { + thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail) utils.Logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) @@ -411,10 +411,10 @@ func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *g return button } -func (this *filesPanel) createOpenFolderButton(fileInformation *octoprint.FileInformation) *gtk.Button { +func (this *filesPanel) createOpenFolderButton(fileResponse *octoprint.FileResponse) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { - this.locationHistory.GoForward(fileInformation.Name) + this.locationHistory.GoForward(fileResponse.Name) this.doLoadFiles() }) @@ -425,16 +425,16 @@ func (this *filesPanel) createOpenFolderButton(fileInformation *octoprint.FileIn return button } -func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInformation *octoprint.FileInformation) *gtk.Button { +func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *octoprint.FileResponse) *gtk.Button { button := utils.MustButton( utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { selectFileRequest := &octoprint.SelectFileRequest{} selectFileRequest.Location = octoprint.Local - selectFileRequest.Path = fileInformation.Path + selectFileRequest.Path = fileResponse.Path selectFileRequest.Print = true - utils.Logger.Infof("Loading file %q", fileInformation.Name) + utils.Logger.Infof("Loading file %q", fileResponse.Name) if err := selectFileRequest.Do(this.UI.Client); err != nil { utils.LogError("files.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) return diff --git a/utils/FileInformationsByDate.go b/utils/FileResponsesSortedByDate.go similarity index 56% rename from utils/FileInformationsByDate.go rename to utils/FileResponsesSortedByDate.go index c2ca83aa..8f7b69ef 100755 --- a/utils/FileInformationsByDate.go +++ b/utils/FileResponsesSortedByDate.go @@ -9,16 +9,16 @@ import ( // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) -type FileInformationsByDate []*octoprint.FileInformation +type FileResponsesSortedByDate []*octoprint.FileResponse -func (this FileInformationsByDate) Len() int { +func (this FileResponsesSortedByDate) Len() int { return len(this) } -func (this FileInformationsByDate) Swap(i, j int) { +func (this FileResponsesSortedByDate) Swap(i, j int) { this[i], this[j] = this[j], this[i] } -func (this FileInformationsByDate) Less(i, j int) bool { +func (this FileResponsesSortedByDate) Less(i, j int) bool { return this[j].Date.Time.Before(this[i].Date.Time) } diff --git a/utils/FileInformationByName.go b/utils/FileResponsesSortedByName.go similarity index 56% rename from utils/FileInformationByName.go rename to utils/FileResponsesSortedByName.go index cad5a71e..9fbd6dd1 100755 --- a/utils/FileInformationByName.go +++ b/utils/FileResponsesSortedByName.go @@ -10,16 +10,16 @@ import ( // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) -type FileInformationsByName []*octoprint.FileInformation +type FileResponsesSortedByName []*octoprint.FileResponse -func (this FileInformationsByName) Len() int { +func (this FileResponsesSortedByName) Len() int { return len(this) } -func (this FileInformationsByName) Swap(i, j int) { +func (this FileResponsesSortedByName) Swap(i, j int) { this[i], this[j] = this[j], this[i] } -func (this FileInformationsByName) Less(i, j int) bool { +func (this FileResponsesSortedByName) Less(i, j int) bool { return this[j].Name > this[i].Name } diff --git a/vendor/github.com/mcuadros/go-octoprint/FileRequest.go b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go index 7ac440b4..8241709a 100755 --- a/vendor/github.com/mcuadros/go-octoprint/FileRequest.go +++ b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go @@ -33,9 +33,9 @@ type FileRequest struct { Recursive bool } -// FileInformation contains information regarding a file. +// FileResponse contains information regarding a file. // https://docs.octoprint.org/en/master/api/datamodel.html#file-information -type FileInformation struct { +type FileResponse struct { // Name is name of the file without path. E.g. “file.gco” for a file // “file.gco” located anywhere in the file system. Name string `json:"name"` @@ -105,8 +105,8 @@ type FileInformation struct { } // IsFolder it returns true if the file is a folder. -func (f *FileInformation) IsFolder() bool { - if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { +func (response *FileResponse) IsFolder() bool { + if len(response.TypePath) == 1 && response.TypePath[0] == "folder" { return true } @@ -114,20 +114,23 @@ func (f *FileInformation) IsFolder() bool { } // Do sends an API request and returns the API response -func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { - uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, - cmd.Location, cmd.Filename, cmd.Recursive, +func (request *FileRequest) Do(c *Client) (*FileResponse, error) { + uri := fmt.Sprintf("%s/%s/%s?recursive=%t", + URIFiles, + request.Location, + request.Filename, + request.Recursive, ) - b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) + bytes, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) if err != nil { return nil, err } - r := &FileInformation{} - if err := json.Unmarshal(b, r); err != nil { + response := &FileResponse{} + if err := json.Unmarshal(bytes, response); err != nil { return nil, err } - return r, err + return response, err } diff --git a/vendor/github.com/mcuadros/go-octoprint/common.go b/vendor/github.com/mcuadros/go-octoprint/common.go index 10df312e..a2ef402b 100755 --- a/vendor/github.com/mcuadros/go-octoprint/common.go +++ b/vendor/github.com/mcuadros/go-octoprint/common.go @@ -33,7 +33,7 @@ type JobResponse struct { // JobInformation contains information regarding the target of the current job. type JobInformation struct { // File is the file that is the target of the current print job. - File FileInformation `json:"file"` + File FileResponse `json:"file"` // EstimatedPrintTime is the estimated print time for the file, in seconds. EstimatedPrintTime float64 `json:"estimatedPrintTime"` @@ -272,8 +272,8 @@ type Profile struct { type FilesResponse struct { // Files is the list of requested files. Might be an empty list if no files // are available - Files []*FileInformation - Children []*FileInformation + Files []*FileResponse + Children []*FileResponse // Free is the amount of disk space in bytes available in the local disk // space (refers to OctoPrint’s `uploads` folder). Only returned if file @@ -281,7 +281,7 @@ type FilesResponse struct { Free uint64 } -// FileInformation is now in FileRequest.go +// FileInformation/FileResponse is now in FileRequest.go // TODO: remove this commented code // FileInformation contains information regarding a file. // type FileInformation struct { @@ -397,11 +397,11 @@ type UploadFileResponse struct { File struct { // Local is the information regarding the file that was just uploaded // to the local storage. - Local *FileInformation `json:"local"` + Local *FileResponse `json:"local"` // SDCard is the information regarding the file that was just uploaded // to the printer’s SD card. - SDCard *FileInformation `json:"sdcard"` + SDCard *FileResponse `json:"sdcard"` } `json:"files"` // Done whether any file processing after upload has already finished or From 5bc295baba6d697af6b0df988f88f7a04f20a431 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 21:39:48 -0800 Subject: [PATCH 13/94] added blank.svg for uniform formatting and alignment --- styles/z-bolt/images/blank.svg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 styles/z-bolt/images/blank.svg diff --git a/styles/z-bolt/images/blank.svg b/styles/z-bolt/images/blank.svg new file mode 100755 index 00000000..f012b4b6 --- /dev/null +++ b/styles/z-bolt/images/blank.svg @@ -0,0 +1,6 @@ + + + + + From a59f468ee98241eb81a9985d25a50c75828415f6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 9 Jan 2021 21:50:30 -0800 Subject: [PATCH 14/94] added styling and alignment for preview thumbnail --- styles/z-bolt/style.css | 2 -- ui/FilesPanel.go | 13 ++++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css index fa6d3d24..0cd0bb10 100755 --- a/styles/z-bolt/style.css +++ b/styles/z-bolt/style.css @@ -46,13 +46,11 @@ progress { } .preview-image-list-item { - margin-left: 76px; margin-bottom: 15px; } - /* Button styles *********************************************************** */ button { background-image: none; diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 3cef5214..63dbe23a 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -354,11 +354,22 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) if imageFromUrlErr == nil { utils.Logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it............") + bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) + + // Initially was setting the horizontal alignment with CSS, but different resolutions + // (eg 800x480 vs 480x320) didn't align correctly, so I added a blank SVG to offset + // the preview thumbnail image. + spacerImage := utils.MustImageFromFileWithSize("blank.svg", this.Scaled(35), this.Scaled(35)) + bottomBox.Add(spacerImage) + + // Still need some CSS for the bottom margin. previewImageStyleContext, _ := previewImage.GetStyleContext() previewImageStyleContext.AddClass("preview-image-list-item") - bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) + // OK, now add the preview image. bottomBox.Add(previewImage) + + // ...and finally add everything to the bottom box/container. listItemBox.Add(bottomBox) } } From 19d600544fd257de6c6fb53dc0b96413c1a06e04 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 10:48:09 -0800 Subject: [PATCH 15/94] refactored thubnail code into addThumbnail(), refactored duplicate UI construction code into functions (like createLabelsBox, createNameLabel, etc...) --- ui/FilesPanel.go | 222 ++++++++++++++++++++++++++--------------------- 1 file changed, 124 insertions(+), 98 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 63dbe23a..795b9686 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -150,50 +150,43 @@ func (this *filesPanel) addRootLocations() { } func (this *filesPanel) addMessage(message string) { - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - nameLabel := utils.MustLabel(message) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) - nameLabel.SetHExpand(true) - nameLabel.SetHAlign(gtk.ALIGN_START) - - labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labelsBox.Add(nameLabel) - labelsBox.SetVExpand(false) - labelsBox.SetVAlign(gtk.ALIGN_CENTER) - labelsBox.SetHAlign(gtk.ALIGN_START) - labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - labelsBoxStyleContext.AddClass("labels-box") + // nameLabel := utils.MustLabel(message) + // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) + // nameLabel.SetHExpand(true) + // nameLabel.SetHAlign(gtk.ALIGN_START) + nameLabel := this.createNameLabel(message) + + // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + // labelsBox.Add(nameLabel) + // labelsBox.SetVExpand(false) + // labelsBox.SetVAlign(gtk.ALIGN_CENTER) + // labelsBox.SetHAlign(gtk.ALIGN_START) + // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + // labelsBoxStyleContext.AddClass("labels-box") + labelsBox := this.createLabelsBox(nameLabel, nil) + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) topBox.Add(labelsBox) - - - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) + listItemBox := this.createListItemBox() listItemBox.Add(topBox) listItemFrame, _ := gtk.FrameNew("") listItemFrame.Add(listItemBox) - this.listBox.Add(listItemFrame) } func (this *filesPanel) addRootLocation(location octoprint.Location, index int) { - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - var itemImage *gtk.Image if location == octoprint.Local { itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) } else { itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) } - topBox.Add(itemImage) + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + topBox.Add(itemImage) name := "" if location == octoprint.Local { @@ -201,23 +194,25 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) } else { name = " SD Card" } - nameLabel := utils.MustLabel(name) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) - nameLabel.SetHExpand(true) - nameLabel.SetHAlign(gtk.ALIGN_START) + // nameLabel := utils.MustLabel(name) + // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) + // nameLabel.SetHExpand(true) + // nameLabel.SetHAlign(gtk.ALIGN_START) + nameLabel := this.createNameLabel(name) infoLabel := utils.MustLabel("") infoLabel.SetHAlign(gtk.ALIGN_START) infoLabel.SetMarkup(" ") - labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labelsBox.Add(nameLabel) - labelsBox.Add(infoLabel) - labelsBox.SetVExpand(false) - labelsBox.SetVAlign(gtk.ALIGN_CENTER) - labelsBox.SetHAlign(gtk.ALIGN_START) - labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - labelsBoxStyleContext.AddClass("labels-box") + // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + // labelsBox.Add(nameLabel) + // labelsBox.Add(infoLabel) + // labelsBox.SetVExpand(false) + // labelsBox.SetVAlign(gtk.ALIGN_CENTER) + // labelsBox.SetHAlign(gtk.ALIGN_START) + // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + // labelsBoxStyleContext.AddClass("labels-box") + labelsBox := this.createLabelsBox(nameLabel, infoLabel) topBox.Add(labelsBox) @@ -234,12 +229,7 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) topBox.Add(actionBox) - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) + listItemBox := this.createListItemBox() listItemBox.Add(topBox) @@ -271,24 +261,23 @@ func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileResponse) { func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) { isFolder := fileResponse.IsFolder() - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - var itemImage *gtk.Image if isFolder { itemImage = utils.MustImageFromFileWithSize("folder.svg", this.Scaled(35), this.Scaled(35)) } else { itemImage = utils.MustImageFromFileWithSize("file-gcode.svg", this.Scaled(35), this.Scaled(35)) } - topBox.Add(itemImage) - + topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + topBox.Add(itemImage) name := fileResponse.Name - nameLabel := utils.MustLabel(name) - nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) - nameLabel.SetHExpand(true) - nameLabel.SetHAlign(gtk.ALIGN_START) + // nameLabel := utils.MustLabel(name) + // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) + // nameLabel.SetHExpand(true) + // nameLabel.SetHAlign(gtk.ALIGN_START) + nameLabel := this.createNameLabel(name) infoLabel := utils.MustLabel("") infoLabel.SetHAlign(gtk.ALIGN_START) @@ -302,14 +291,15 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) )) } - labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - labelsBox.Add(nameLabel) - labelsBox.Add(infoLabel) - labelsBox.SetVExpand(false) - labelsBox.SetVAlign(gtk.ALIGN_CENTER) - labelsBox.SetHAlign(gtk.ALIGN_START) - labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - labelsBoxStyleContext.AddClass("labels-box") + // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + // labelsBox.Add(nameLabel) + // labelsBox.Add(infoLabel) + // labelsBox.SetVExpand(false) + // labelsBox.SetVAlign(gtk.ALIGN_CENTER) + // labelsBox.SetHAlign(gtk.ALIGN_START) + // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + // labelsBoxStyleContext.AddClass("labels-box") + labelsBox := this.createLabelsBox(nameLabel, infoLabel) topBox.Add(labelsBox) @@ -330,12 +320,7 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) + listItemBox := this.createListItemBox() listItemBox.Add(topBox) @@ -343,42 +328,69 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) + if !isFolder { + this.addThumbnail(fileResponse, listItemBox) + } - if !isFolder { - if fileResponse.Thumbnail != "" { - thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail) - utils.Logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) - previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) - if imageFromUrlErr == nil { - utils.Logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it............") - bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) + listItemFrame, _ := gtk.FrameNew("") + listItemFrame.Add(listItemBox) - // Initially was setting the horizontal alignment with CSS, but different resolutions - // (eg 800x480 vs 480x320) didn't align correctly, so I added a blank SVG to offset - // the preview thumbnail image. - spacerImage := utils.MustImageFromFileWithSize("blank.svg", this.Scaled(35), this.Scaled(35)) - bottomBox.Add(spacerImage) - // Still need some CSS for the bottom margin. - previewImageStyleContext, _ := previewImage.GetStyleContext() - previewImageStyleContext.AddClass("preview-image-list-item") - // OK, now add the preview image. - bottomBox.Add(previewImage) + itemButtonStyleContext, _ := itemButton.GetStyleContext() + listItemBoxStyleContext, _:= listItemBox.GetStyleContext() + listItemFrameStyleContext, _ := listItemFrame.GetStyleContext() + if index % 2 != 0 { + itemButtonStyleContext.AddClass("list-item-nth-child-even") + listItemBoxStyleContext.AddClass("list-item-nth-child-even") + listItemFrameStyleContext.AddClass("list-item-nth-child-even") + } - // ...and finally add everything to the bottom box/container. - listItemBox.Add(bottomBox) - } - } + this.listBox.Add(listItemFrame) +} + + + +func (this *filesPanel) createLabelsBox(nameLabel, infoLabel *gtk.Label) *gtk.Box { + labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + if nameLabel != nil { + labelsBox.Add(nameLabel) } + if infoLabel != nil { + labelsBox.Add(infoLabel) + } + labelsBox.SetVExpand(false) + labelsBox.SetVAlign(gtk.ALIGN_CENTER) + labelsBox.SetHAlign(gtk.ALIGN_START) + labelsBoxStyleContext, _ := labelsBox.GetStyleContext() + labelsBoxStyleContext.AddClass("labels-box") + return labelsBox +} +func (this *filesPanel) createNameLabel(name string) *gtk.Label { + nameLabel := utils.MustLabel(name) + // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) + nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) + nameLabel.SetHExpand(true) + nameLabel.SetHAlign(gtk.ALIGN_START) + return nameLabel +} +func (this *filesPanel) createListItemBox() *gtk.Box { + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) + listItemBox.SetMarginTop(1) + listItemBox.SetMarginBottom(1) + listItemBox.SetMarginStart(15) + listItemBox.SetMarginEnd(15) + listItemBox.SetHExpand(true) + return listItemBox +} @@ -386,22 +398,36 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) +func (this *filesPanel) addThumbnail(fileResponse *octoprint.FileResponse, listItemBox *gtk.Box) { + if fileResponse.Thumbnail != "" { + utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) - listItemFrame, _ := gtk.FrameNew("") - listItemFrame.Add(listItemBox) + thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail) + utils.Logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) + previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) + if imageFromUrlErr == nil { + utils.Logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it...") + bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) - itemButtonStyleContext, _ := itemButton.GetStyleContext() - listItemBoxStyleContext, _:= listItemBox.GetStyleContext() - listItemFrameStyleContext, _ := listItemFrame.GetStyleContext() - if index % 2 != 0 { - itemButtonStyleContext.AddClass("list-item-nth-child-even") - listItemBoxStyleContext.AddClass("list-item-nth-child-even") - listItemFrameStyleContext.AddClass("list-item-nth-child-even") - } + // Initially was setting the horizontal alignment with CSS, but different resolutions + // (eg 800x480 vs 480x320) didn't align correctly, so I added a blank SVG to offset + // the preview thumbnail image. + spacerImage := utils.MustImageFromFileWithSize("blank.svg", this.Scaled(35), this.Scaled(35)) + bottomBox.Add(spacerImage) - this.listBox.Add(listItemFrame) + // Still need some CSS for the bottom margin. + previewImageStyleContext, _ := previewImage.GetStyleContext() + previewImageStyleContext.AddClass("preview-image-list-item") + + // OK, now add the preview image. + bottomBox.Add(previewImage) + + // ...and finally add everything to the bottom box/container. + listItemBox.Add(bottomBox) + } + } } From 79d2794abf494089ab46ea5e1611897600e1029b Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 10:50:42 -0800 Subject: [PATCH 16/94] removed commentdd code and extra whitespace --- ui/FilesPanel.go | 69 ------------------------------------------------ 1 file changed, 69 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 795b9686..76d88bc7 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -150,19 +150,7 @@ func (this *filesPanel) addRootLocations() { } func (this *filesPanel) addMessage(message string) { - // nameLabel := utils.MustLabel(message) - // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(message))) - // nameLabel.SetHExpand(true) - // nameLabel.SetHAlign(gtk.ALIGN_START) nameLabel := this.createNameLabel(message) - - // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - // labelsBox.Add(nameLabel) - // labelsBox.SetVExpand(false) - // labelsBox.SetVAlign(gtk.ALIGN_CENTER) - // labelsBox.SetHAlign(gtk.ALIGN_START) - // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - // labelsBoxStyleContext.AddClass("labels-box") labelsBox := this.createLabelsBox(nameLabel, nil) topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) @@ -194,26 +182,13 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) } else { name = " SD Card" } - // nameLabel := utils.MustLabel(name) - // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) - // nameLabel.SetHExpand(true) - // nameLabel.SetHAlign(gtk.ALIGN_START) nameLabel := this.createNameLabel(name) infoLabel := utils.MustLabel("") infoLabel.SetHAlign(gtk.ALIGN_START) infoLabel.SetMarkup(" ") - // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - // labelsBox.Add(nameLabel) - // labelsBox.Add(infoLabel) - // labelsBox.SetVExpand(false) - // labelsBox.SetVAlign(gtk.ALIGN_CENTER) - // labelsBox.SetHAlign(gtk.ALIGN_START) - // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - // labelsBoxStyleContext.AddClass("labels-box") labelsBox := this.createLabelsBox(nameLabel, infoLabel) - topBox.Add(labelsBox) @@ -228,11 +203,9 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) actionBox.Add(itemButton) topBox.Add(actionBox) - listItemBox := this.createListItemBox() listItemBox.Add(topBox) - listItemFrame, _ := gtk.FrameNew("") listItemFrame.Add(listItemBox) @@ -271,12 +244,7 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) topBox.Add(itemImage) - name := fileResponse.Name - // nameLabel := utils.MustLabel(name) - // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) - // nameLabel.SetHExpand(true) - // nameLabel.SetHAlign(gtk.ALIGN_START) nameLabel := this.createNameLabel(name) infoLabel := utils.MustLabel("") @@ -291,21 +259,9 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) )) } - // labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - // labelsBox.Add(nameLabel) - // labelsBox.Add(infoLabel) - // labelsBox.SetVExpand(false) - // labelsBox.SetVAlign(gtk.ALIGN_CENTER) - // labelsBox.SetHAlign(gtk.ALIGN_START) - // labelsBoxStyleContext, _ := labelsBox.GetStyleContext() - // labelsBoxStyleContext.AddClass("labels-box") labelsBox := this.createLabelsBox(nameLabel, infoLabel) - topBox.Add(labelsBox) - - - var itemButton *gtk.Button if isFolder { itemButton = this.createOpenFolderButton(fileResponse) @@ -317,29 +273,16 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) actionBox.Add(itemButton) topBox.Add(actionBox) - - - listItemBox := this.createListItemBox() listItemBox.Add(topBox) - - - - - if !isFolder { this.addThumbnail(fileResponse, listItemBox) } - - - listItemFrame, _ := gtk.FrameNew("") listItemFrame.Add(listItemBox) - - itemButtonStyleContext, _ := itemButton.GetStyleContext() listItemBoxStyleContext, _:= listItemBox.GetStyleContext() listItemFrameStyleContext, _ := listItemFrame.GetStyleContext() @@ -352,8 +295,6 @@ func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) this.listBox.Add(listItemFrame) } - - func (this *filesPanel) createLabelsBox(nameLabel, infoLabel *gtk.Label) *gtk.Box { labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) if nameLabel != nil { @@ -373,7 +314,6 @@ func (this *filesPanel) createLabelsBox(nameLabel, infoLabel *gtk.Label) *gtk.Bo func (this *filesPanel) createNameLabel(name string) *gtk.Label { nameLabel := utils.MustLabel(name) - // nameLabel.SetMarkup(fmt.Sprintf("%s", utils.StrEllipsis(name))) nameLabel.SetMarkup(fmt.Sprintf("%s", utils.TruncateString(name, 30))) nameLabel.SetHExpand(true) nameLabel.SetHAlign(gtk.ALIGN_START) @@ -392,12 +332,6 @@ func (this *filesPanel) createListItemBox() *gtk.Box { return listItemBox } - - - - - - func (this *filesPanel) addThumbnail(fileResponse *octoprint.FileResponse, listItemBox *gtk.Box) { if fileResponse.Thumbnail != "" { utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) @@ -486,9 +420,6 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileRespo return button } - - - /* func (this *filesPanel) isReady() bool { state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client) From 5c958ce32a1d5fb33d82d44fe4662f0a72706581 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 19:51:45 -0800 Subject: [PATCH 17/94] fixed printing bug where wrong source locations was being used --- ui/FilesPanel.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 76d88bc7..c42098d1 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -401,13 +401,16 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileRespo utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { selectFileRequest := &octoprint.SelectFileRequest{} - selectFileRequest.Location = octoprint.Local + + // Set the location to "local" or "sdcard" + selectFileRequest.Location = this.locationHistory.Locations[0] + selectFileRequest.Path = fileResponse.Path selectFileRequest.Print = true utils.Logger.Infof("Loading file %q", fileResponse.Name) if err := selectFileRequest.Do(this.UI.Client); err != nil { - utils.LogError("files.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) + utils.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) return } }), From 7684f6de4d6ae855f17cec645f310d8e43e1d309 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 19:55:54 -0800 Subject: [PATCH 18/94] renamed file.go to file_utils.go --- utils/{file.go => file_utils.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename utils/{file.go => file_utils.go} (100%) diff --git a/utils/file.go b/utils/file_utils.go similarity index 100% rename from utils/file.go rename to utils/file_utils.go From 87e029f74faf5b93af669fd39c58b0985465ad2b Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 19:59:41 -0800 Subject: [PATCH 19/94] added call to GetObfuscatedValue() in dumpObfuscatedEnvironmentVariable() --- utils/environment.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/environment.go b/utils/environment.go index f4f038be..bae21531 100755 --- a/utils/environment.go +++ b/utils/environment.go @@ -113,9 +113,11 @@ func dumpObfuscatedEnvironmentVariable(key string) { value := os.Getenv(key) if value == "" { value = ">>MISSING<<" + } else { + value = GetObfuscatedValue(value) } - Logger.Infof("key: %q, value: %q", key, GetObfuscatedValue(value)) + Logger.Infof("key: %q, value: %q", key, value) } func GetObfuscatedValue(value string) string { From bc352f8b5a6599e4fb346d320b7c49f072dea0dd Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 10 Jan 2021 20:03:55 -0800 Subject: [PATCH 20/94] more Break up the Monolith! changes, continued to seperate common.go and other files into seperate individual files --- .../mcuadros/go-octoprint/FileRequest.go | 2 + .../mcuadros/go-octoprint/FullStateRequest.go | 94 ++++++++++ .../mcuadros/go-octoprint/JobInformation.go | 33 ++++ .../mcuadros/go-octoprint/JobRequest.go | 46 +++++ .../go-octoprint/ProgressInformation.go | 29 +++ .../go-octoprint/SelectFileRequest.go | 48 +++++ .../mcuadros/go-octoprint/TemperatureData.go | 21 +++ .../go-octoprint/TemperatureStateResponse.go | 47 +++++ .../mcuadros/go-octoprint/common.go | 163 +++++++++-------- .../github.com/mcuadros/go-octoprint/files.go | 69 +++---- .../github.com/mcuadros/go-octoprint/job.go | 37 ++-- .../mcuadros/go-octoprint/printer.go | 168 +++++++++--------- 12 files changed, 548 insertions(+), 209 deletions(-) create mode 100755 vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/JobInformation.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/JobRequest.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/ProgressInformation.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/SelectFileRequest.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/TemperatureData.go create mode 100755 vendor/github.com/mcuadros/go-octoprint/TemperatureStateResponse.go diff --git a/vendor/github.com/mcuadros/go-octoprint/FileRequest.go b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go index 8241709a..6dcbf212 100755 --- a/vendor/github.com/mcuadros/go-octoprint/FileRequest.go +++ b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go @@ -113,6 +113,8 @@ func (response *FileResponse) IsFolder() bool { return false } +const URIFiles = "/api/files" + // Do sends an API request and returns the API response func (request *FileRequest) Do(c *Client) (*FileResponse, error) { uri := fmt.Sprintf("%s/%s/%s?recursive=%t", diff --git a/vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go b/vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go new file mode 100755 index 00000000..6de286fc --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go @@ -0,0 +1,94 @@ +package octoprint + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + "log" + "strings" +) + +// FullStateRequest retrieves the current state of the printer. +type FullStateRequest struct { + // bytes if true retrieve the temperature history. + IncludeHistory bool + + // Limit limits the amount of returned history data points. + Limit int + + // Exclude list of fields to exclude from the response (e.g. if not + // needed by the client). Valid values to supply here are `temperature`, + // `sd` and `state`. + Exclude []string +} + +// FullStateResponse contains informantion about the current state of the printer. +type FullStateResponse struct { + // TemperatureStateResponse is the printer’s temperature state data. + Temperature TemperatureStateResponse `json:"temperature"` + + // SD is the printer’s sd state data. + SD SDState `json:"sd"` + + // State is the printer’s general state. + State PrinterState `json:"state"` +} + +const URIPrinter = "/api/printer" + +// Do sends an API request and returns the API response. +func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { + uri := fmt.Sprintf( + "%s?history=%t&limit=%d&exclude=%s", + URIPrinter, + cmd.IncludeHistory, + cmd.Limit, + strings.Join(cmd.Exclude, ","), + ) + + log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) + //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state + /* + { + "temperature": { + "bed": { + "actual": 26.9, + "offset": 0, + "target": 0.0 + }, + "history": [ + { + "bed": { + "actual": 26.9, + "target": 0.0 + }, + "time": 1598235178, + "tool0": { + "actual": 35.4, + "target": 0.0 + } + } + ], + "tool0": { + "actual": 35.4, + "offset": 0, + "target": 0.0 + } + } + } + */ + + + bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) + if err != nil { + return nil, err + } + + response := &FullStateResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/vendor/github.com/mcuadros/go-octoprint/JobInformation.go b/vendor/github.com/mcuadros/go-octoprint/JobInformation.go new file mode 100755 index 00000000..e2bebb51 --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/JobInformation.go @@ -0,0 +1,33 @@ +package octoprint + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// Job information +// https://docs.octoprint.org/en/master/api/datamodel.html#job-information + + +// JobInformation contains information regarding the target of the current job. +type JobInformation struct { + // File is the file that is the target of the current print job. + File FileResponse `json:"file"` + + // EstimatedPrintTime is the estimated print time for the file, in seconds. + EstimatedPrintTime float64 `json:"estimatedPrintTime"` + + // LastPrintTime is the print time of the last print of the file, in seconds. + LastPrintTime float64 `json:"lastPrintTime"` + + // Filament contains Information regarding the estimated filament usage of the print job. + Filament struct { + // Length of filament used, in mm + Length float64 `json:"length"` + + // Volume of filament used, in cm³ + Volume float64 `json:"volume"` + } `json:"filament"` +} diff --git a/vendor/github.com/mcuadros/go-octoprint/JobRequest.go b/vendor/github.com/mcuadros/go-octoprint/JobRequest.go new file mode 100755 index 00000000..00e4a47b --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/JobRequest.go @@ -0,0 +1,46 @@ +package octoprint + +import ( + // "bytes" + "encoding/json" + // "io" + // "log" +) + +// JobRequest retrieve information about the current job (if there is one). +type JobRequest struct{} + + + +// Job information response +// https://docs.octoprint.org/en/master/api/job.html#job-information-response + +// JobResponse is the response from a job command. +type JobResponse struct { + // Job contains information regarding the target of the current print job. + Job JobInformation `json:"job"` + + // Progress contains information regarding the progress of the current job. + Progress ProgressInformation `json:"progress"` + + //State StateInformation `json:"state"` + State string `json:"state"` +} + +// https://docs.octoprint.org/en/master/api/job.html +const JobTool = "/api/job" + +// Do sends an API request and returns the API response. +func (cmd *JobRequest) Do(client *Client) (*JobResponse, error) { + bytes, err := client.doJSONRequest("GET", JobTool, nil, nil) + if err != nil { + return nil, err + } + + response := &JobResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/vendor/github.com/mcuadros/go-octoprint/ProgressInformation.go b/vendor/github.com/mcuadros/go-octoprint/ProgressInformation.go new file mode 100755 index 00000000..9bb2274f --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/ProgressInformation.go @@ -0,0 +1,29 @@ +package octoprint + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// Progress information +// https://docs.octoprint.org/en/master/api/datamodel.html#progress-information + +// ProgressInformation contains information regarding the progress of the current print job. +type ProgressInformation struct { + // Completion percentage of completion of the current print job. + Completion float64 `json:"completion"` + + // FilePosition current position in the file being printed, in bytes from the beginning. + FilePosition uint64 `json:"filepos"` + + // PrintTime is time already spent printing, in seconds. + PrintTime float64 `json:"printTime"` + + // PrintTimeLeft is estimate of time left to print, in seconds. + PrintTimeLeft float64 `json:"printTimeLeft"` + + // Origin of the current time left estimate. + PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` +} diff --git a/vendor/github.com/mcuadros/go-octoprint/SelectFileRequest.go b/vendor/github.com/mcuadros/go-octoprint/SelectFileRequest.go new file mode 100755 index 00000000..6206a6fa --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/SelectFileRequest.go @@ -0,0 +1,48 @@ +package octoprint + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + // "mime/multipart" +) + +// SelectFileRequest selects a file for printing. +type SelectFileRequest struct { + // Location is target location on which to send the command for is located, + // either local (for OctoPrint’s uploads folder) or sdcard for the + // printer’s SD card (if available). + Location Location `json:"-"` + + // Path of the file for which to issue the command. + Path string `json:"-"` + + // Print, if set to true the file will start printing directly after + // selection. If the printer is not operational when this parameter is + // present and set to true, the request will fail with a response of + // 409 Conflict. + Print bool `json:"print"` +} + +// Do sends an API request and returns an error if any. +func (cmd *SelectFileRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) + _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) + return err +} + +func (cmd *SelectFileRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + SelectFileRequest + }{ + Command: "select", + SelectFileRequest: *cmd, + }) +} diff --git a/vendor/github.com/mcuadros/go-octoprint/TemperatureData.go b/vendor/github.com/mcuadros/go-octoprint/TemperatureData.go new file mode 100755 index 00000000..f05a98f9 --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/TemperatureData.go @@ -0,0 +1,21 @@ +package octoprint + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// TemperatureData is temperature stats for a tool. +type TemperatureData struct { + // Actual current temperature. + Actual float64 `json:"actual"` + + // Target temperature, may be nil if no target temperature is set. + Target float64 `json:"target"` + + // Offset currently configured temperature offset to apply, will be left + // out for historic temperature information. + Offset float64 `json:"offset"` +} diff --git a/vendor/github.com/mcuadros/go-octoprint/TemperatureStateResponse.go b/vendor/github.com/mcuadros/go-octoprint/TemperatureStateResponse.go new file mode 100755 index 00000000..3818a0bb --- /dev/null +++ b/vendor/github.com/mcuadros/go-octoprint/TemperatureStateResponse.go @@ -0,0 +1,47 @@ +package octoprint + +import ( + "encoding/json" + // "strconv" + // "strings" + // "time" +) + + +// TODO: add request +// TODO: add Do() + + +// TemperatureState is the printer’s temperature state data. +type TemperatureStateResponse temperatureStateResponse + +type temperatureStateResponse struct { + // Current temperature stats. + CurrentTemperatureData map[string]TemperatureData `json:"current"` + + // Temperature history. + History []*HistoricTemperatureData `json:"history"` +} + +func (r *TemperatureStateResponse) UnmarshalJSON(bytes []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(bytes, &raw); err != nil { + return err + } + + history := raw["history"] + delete(raw, "history") + bytes, _ = json.Marshal(map[string]interface{}{ + "current": raw, + "history": history, + }) + + i := &temperatureStateResponse{} + if err := json.Unmarshal(bytes, i); err != nil { + return err + } + + *r = TemperatureStateResponse(*i) + + return nil +} diff --git a/vendor/github.com/mcuadros/go-octoprint/common.go b/vendor/github.com/mcuadros/go-octoprint/common.go index a2ef402b..0024c512 100755 --- a/vendor/github.com/mcuadros/go-octoprint/common.go +++ b/vendor/github.com/mcuadros/go-octoprint/common.go @@ -17,107 +17,118 @@ const ( ZAxis Axis = "z" ) +// JobResponse is now in JobRequest.go +// // JobResponse is the response from a job command. +// type JobResponse struct { +// // Job contains information regarding the target of the current print job. +// Job JobInformation `json:"job"` -// JobResponse is the response from a job command. -type JobResponse struct { - // Job contains information regarding the target of the current print job. - Job JobInformation `json:"job"` +// // Progress contains information regarding the progress of the current job. +// Progress ProgressInformation `json:"progress"` - // Progress contains information regarding the progress of the current job. - Progress ProgressInformation `json:"progress"` +// //State StateInformation `json:"state"` +// State string `json:"state"` +// } - //State StateInformation `json:"state"` - State string `json:"state"` -} -// JobInformation contains information regarding the target of the current job. -type JobInformation struct { - // File is the file that is the target of the current print job. - File FileResponse `json:"file"` - // EstimatedPrintTime is the estimated print time for the file, in seconds. - EstimatedPrintTime float64 `json:"estimatedPrintTime"` +// JobInformation i no in JobInformation.go +// // JobInformation contains information regarding the target of the current job. +// type JobInformation struct { +// // File is the file that is the target of the current print job. +// File FileResponse `json:"file"` - // LastPrintTime is the print time of the last print of the file, in seconds. - LastPrintTime float64 `json:"lastPrintTime"` +// // EstimatedPrintTime is the estimated print time for the file, in seconds. +// EstimatedPrintTime float64 `json:"estimatedPrintTime"` - // Filament contains Information regarding the estimated filament - // usage of the print job. - Filament struct { - // Length of filament used, in mm - Length float64 `json:"length"` - // Volume of filament used, in cm³ - Volume float64 `json:"volume"` - } `json:"filament"` +// // LastPrintTime is the print time of the last print of the file, in seconds. +// LastPrintTime float64 `json:"lastPrintTime"` - FilePosition uint64 `json:"filepos"` -} +// // Filament contains Information regarding the estimated filament +// // usage of the print job. +// Filament struct { +// // Length of filament used, in mm +// Length float64 `json:"length"` +// // Volume of filament used, in cm³ +// Volume float64 `json:"volume"` +// } `json:"filament"` + +// FilePosition uint64 `json:"filepos"` +// } + + +// ProgressInformation is now in ProgressInformation.go // ProgressInformation contains information regarding the progress of the // current print job. -type ProgressInformation struct { - // Completion percentage of completion of the current print job. - Completion float64 `json:"completion"` +// type ProgressInformation struct { +// // Completion percentage of completion of the current print job. +// Completion float64 `json:"completion"` - // FilePosition current position in the file being printed, in bytes - // from the beginning. - FilePosition uint64 `json:"filepos"` +// // FilePosition current position in the file being printed, in bytes +// // from the beginning. +// FilePosition uint64 `json:"filepos"` - // PrintTime is time already spent printing, in seconds - PrintTime float64 `json:"printTime"` +// // PrintTime is time already spent printing, in seconds +// PrintTime float64 `json:"printTime"` - // PrintTimeLeft is estimate of time left to print, in seconds - PrintTimeLeft float64 `json:"printTimeLeft"` +// // PrintTimeLeft is estimate of time left to print, in seconds +// PrintTimeLeft float64 `json:"printTimeLeft"` - // Origin of the current time left estimate - PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` -} +// // Origin of the current time left estimate +// PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` +// } -// TemperatureState is the printer’s temperature state data. -type TemperatureStateResponse temperatureStateResponse -type temperatureStateResponse struct { - // Current temperature stats. - CurrentTemperatureData map[string]TemperatureData `json:"current"` - // Temperature history. - History []*HistoricTemperatureData `json:"history"` -} -func (r *TemperatureStateResponse) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } +// TemperatureStateResponse is now in TemperatureStateResponse.go +// // TemperatureState is the printer’s temperature state data. +// type TemperatureStateResponse temperatureStateResponse - history := raw["history"] - delete(raw, "history") - b, _ = json.Marshal(map[string]interface{}{ - "current": raw, - "history": history, - }) +// type temperatureStateResponse struct { +// // Current temperature stats. +// CurrentTemperatureData map[string]TemperatureData `json:"current"` - i := &temperatureStateResponse{} - if err := json.Unmarshal(b, i); err != nil { - return err - } +// // Temperature history. +// History []*HistoricTemperatureData `json:"history"` +// } - *r = TemperatureStateResponse(*i) - return nil -} +// func (r *TemperatureStateResponse) UnmarshalJSON(b []byte) error { +// var raw map[string]interface{} +// if err := json.Unmarshal(b, &raw); err != nil { +// return err +// } -// TemperatureData is temperature stats for a tool. -type TemperatureData struct { - // Actual current temperature. - Actual float64 `json:"actual"` +// history := raw["history"] +// delete(raw, "history") +// b, _ = json.Marshal(map[string]interface{}{ +// "current": raw, +// "history": history, +// }) - // Target temperature, may be nil if no target temperature is set. - Target float64 `json:"target"` +// i := &temperatureStateResponse{} +// if err := json.Unmarshal(b, i); err != nil { +// return err +// } - // Offset currently configured temperature offset to apply, will be left - // out for historic temperature information. - Offset float64 `json:"offset"` -} +// *r = TemperatureStateResponse(*i) +// return nil +// } + +// TemperatureData is now in TemperatureData.go +// // TemperatureData is temperature stats for a tool. +// type TemperatureData struct { +// // Actual current temperature. +// Actual float64 `json:"actual"` + +// // Target temperature, may be nil if no target temperature is set. +// Target float64 `json:"target"` + +// // Offset currently configured temperature offset to apply, will be left +// // out for historic temperature information. +// Offset float64 `json:"offset"` +// } // PrinterState current state of the printer. type PrinterState struct { diff --git a/vendor/github.com/mcuadros/go-octoprint/files.go b/vendor/github.com/mcuadros/go-octoprint/files.go index 85063946..73542af9 100755 --- a/vendor/github.com/mcuadros/go-octoprint/files.go +++ b/vendor/github.com/mcuadros/go-octoprint/files.go @@ -11,7 +11,7 @@ import ( type Location string const ( - URIFiles = "/api/files" + // URIFiles = "/api/files" Local Location = "local" SDCard Location = "sdcard" @@ -211,39 +211,40 @@ func (req *DeleteFileRequest) Do(c *Client) error { return nil } -// SelectFileRequest selects a file for printing. -type SelectFileRequest struct { - // Location is target location on which to send the command for is located, - // either local (for OctoPrint’s uploads folder) or sdcard for the - // printer’s SD card (if available) - Location Location `json:"-"` - // Path of the file for which to issue the command - Path string `json:"-"` - // Print, if set to true the file will start printing directly after - // selection. If the printer is not operational when this parameter is - // present and set to true, the request will fail with a response of - // 409 Conflict. - Print bool `json:"print"` -} +// SelectFileRequest is now in SelectFileRequest.go +// // SelectFileRequest selects a file for printing. +// type SelectFileRequest struct { +// // Location is target location on which to send the command for is located, +// // either local (for OctoPrint’s uploads folder) or sdcard for the +// // printer’s SD card (if available) +// Location Location `json:"-"` +// // Path of the file for which to issue the command +// Path string `json:"-"` +// // Print, if set to true the file will start printing directly after +// // selection. If the printer is not operational when this parameter is +// // present and set to true, the request will fail with a response of +// // 409 Conflict. +// Print bool `json:"print"` +// } -// Do sends an API request and returns an error if any. -func (cmd *SelectFileRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } +// // Do sends an API request and returns an error if any. +// func (cmd *SelectFileRequest) Do(c *Client) error { +// b := bytes.NewBuffer(nil) +// if err := cmd.encode(b); err != nil { +// return err +// } - uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) - _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) - return err -} +// uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) +// _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) +// return err +// } -func (cmd *SelectFileRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - SelectFileRequest - }{ - Command: "select", - SelectFileRequest: *cmd, - }) -} +// func (cmd *SelectFileRequest) encode(w io.Writer) error { +// return json.NewEncoder(w).Encode(struct { +// Command string `json:"command"` +// SelectFileRequest +// }{ +// Command: "select", +// SelectFileRequest: *cmd, +// }) +// } diff --git a/vendor/github.com/mcuadros/go-octoprint/job.go b/vendor/github.com/mcuadros/go-octoprint/job.go index d3372832..cde0c232 100755 --- a/vendor/github.com/mcuadros/go-octoprint/job.go +++ b/vendor/github.com/mcuadros/go-octoprint/job.go @@ -7,29 +7,36 @@ import ( "log" ) -const JobTool = "/api/job" var JobToolErrors = statusMapping{ 409: "Printer is not operational or the current print job state does not match the preconditions for the command.", } -// JobRequest retrieve information about the current job (if there is one). -type JobRequest struct{} -// Do sends an API request and returns the API response. -func (cmd *JobRequest) Do(c *Client) (*JobResponse, error) { - bytes, err := c.doJSONRequest("GET", JobTool, nil, nil) - if err != nil { - return nil, err - } - response := &JobResponse{} - if err := json.Unmarshal(bytes, response); err != nil { - return nil, err - } - return response, err -} +// JobRequest is now in JobRequest.go +// // JobRequest retrieve information about the current job (if there is one). +// type JobRequest struct{} + +// // Do sends an API request and returns the API response. +// func (cmd *JobRequest) Do(c *Client) (*JobResponse, error) { +// bytes, err := c.doJSONRequest("GET", JobTool, nil, nil) +// if err != nil { +// return nil, err +// } + +// response := &JobResponse{} +// if err := json.Unmarshal(bytes, response); err != nil { +// return nil, err +// } + +// return response, err +// } + + + + // StartRequest starts the print of the currently selected file. type StartRequest struct{} diff --git a/vendor/github.com/mcuadros/go-octoprint/printer.go b/vendor/github.com/mcuadros/go-octoprint/printer.go index f1bb3a43..8a3cde4b 100755 --- a/vendor/github.com/mcuadros/go-octoprint/printer.go +++ b/vendor/github.com/mcuadros/go-octoprint/printer.go @@ -6,11 +6,11 @@ import ( "fmt" "io" "log" - "strings" + // "strings" ) const ( - URIPrinter = "/api/printer" + // URIPrinter = "/api/printer" URIPrintHead = "/api/printer/printhead" URIPrintTool = "/api/printer/tool" URIPrintBed = "/api/printer/bed" @@ -44,88 +44,88 @@ var ( - -// FullStateRequest retrieves the current state of the printer. -type FullStateRequest struct { - // bytes if true retrieve the temperature history. - IncludeHistory bool - - // Limit limits the amount of returned history data points. - Limit int - - // Exclude list of fields to exclude from the response (e.g. if not - // needed by the client). Valid values to supply here are `temperature`, - // `sd` and `state`. - Exclude []string -} - -// FullStateResponse contains informantion about the current state of the printer. -type FullStateResponse struct { - // TemperatureStateResponse is the printer’s temperature state data. - Temperature TemperatureStateResponse `json:"temperature"` - - // SD is the printer’s sd state data. - SD SDState `json:"sd"` - - // State is the printer’s general state. - State PrinterState `json:"state"` -} - -// Do sends an API request and returns the API response. -func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { - uri := fmt.Sprintf( - "%s?history=%t&limit=%d&exclude=%s", - URIPrinter, - cmd.IncludeHistory, - cmd.Limit, - strings.Join(cmd.Exclude, ","), - ) - - log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) - //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state - /* - { - "temperature": { - "bed": { - "actual": 26.9, - "offset": 0, - "target": 0.0 - }, - "history": [ - { - "bed": { - "actual": 26.9, - "target": 0.0 - }, - "time": 1598235178, - "tool0": { - "actual": 35.4, - "target": 0.0 - } - } - ], - "tool0": { - "actual": 35.4, - "offset": 0, - "target": 0.0 - } - } - } - */ - - - bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) - if err != nil { - return nil, err - } - - response := &FullStateResponse{} - if err := json.Unmarshal(bytes, response); err != nil { - return nil, err - } - - return response, err -} +// FullStateRequest has been moved to FullStateRequest.go +// // FullStateRequest retrieves the current state of the printer. +// type FullStateRequest struct { +// // bytes if true retrieve the temperature history. +// IncludeHistory bool + +// // Limit limits the amount of returned history data points. +// Limit int + +// // Exclude list of fields to exclude from the response (e.g. if not +// // needed by the client). Valid values to supply here are `temperature`, +// // `sd` and `state`. +// Exclude []string +// } + +// // FullStateResponse contains informantion about the current state of the printer. +// type FullStateResponse struct { +// // TemperatureStateResponse is the printer’s temperature state data. +// Temperature TemperatureStateResponse `json:"temperature"` + +// // SD is the printer’s sd state data. +// SD SDState `json:"sd"` + +// // State is the printer’s general state. +// State PrinterState `json:"state"` +// } + +// // Do sends an API request and returns the API response. +// func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { +// uri := fmt.Sprintf( +// "%s?history=%t&limit=%d&exclude=%s", +// URIPrinter, +// cmd.IncludeHistory, +// cmd.Limit, +// strings.Join(cmd.Exclude, ","), +// ) + +// log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) +// //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state +// /* +// { +// "temperature": { +// "bed": { +// "actual": 26.9, +// "offset": 0, +// "target": 0.0 +// }, +// "history": [ +// { +// "bed": { +// "actual": 26.9, +// "target": 0.0 +// }, +// "time": 1598235178, +// "tool0": { +// "actual": 35.4, +// "target": 0.0 +// } +// } +// ], +// "tool0": { +// "actual": 35.4, +// "offset": 0, +// "target": 0.0 +// } +// } +// } +// */ + + +// bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) +// if err != nil { +// return nil, err +// } + +// response := &FullStateResponse{} +// if err := json.Unmarshal(bytes, response); err != nil { +// return nil, err +// } + +// return response, err +// } From bc465c0e116b883b3eded3e9fee9abdfea5d9170 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:19:21 -0800 Subject: [PATCH 21/94] added additional speed dial images --- docs/ButtonImages.html | 26 +++++++++++++++++ styles/z-bolt/images/speed-0%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-100%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-17%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-34%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-50%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-67%.svg | 45 +++++++++++++++++++++++++++++ styles/z-bolt/images/speed-83%.svg | 45 +++++++++++++++++++++++++++++ 8 files changed, 341 insertions(+) create mode 100644 styles/z-bolt/images/speed-0%.svg create mode 100644 styles/z-bolt/images/speed-100%.svg create mode 100644 styles/z-bolt/images/speed-17%.svg create mode 100644 styles/z-bolt/images/speed-34%.svg create mode 100644 styles/z-bolt/images/speed-50%.svg create mode 100644 styles/z-bolt/images/speed-67%.svg create mode 100644 styles/z-bolt/images/speed-83%.svg diff --git a/docs/ButtonImages.html b/docs/ButtonImages.html index 50d98c8c..ee6b0165 100755 --- a/docs/ButtonImages.html +++ b/docs/ButtonImages.html @@ -227,6 +227,32 @@
shutdown
+ + + + +
speed-0%
+ + +
speed-17%
+ + +
speed-34%
+ + +
speed-50%
+ + +
speed-83%
+ + +
speed-100%
+ + + + + +
speed-fast
diff --git a/styles/z-bolt/images/speed-0%.svg b/styles/z-bolt/images/speed-0%.svg new file mode 100644 index 00000000..05a24260 --- /dev/null +++ b/styles/z-bolt/images/speed-0%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-100%.svg b/styles/z-bolt/images/speed-100%.svg new file mode 100644 index 00000000..b50ef036 --- /dev/null +++ b/styles/z-bolt/images/speed-100%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-17%.svg b/styles/z-bolt/images/speed-17%.svg new file mode 100644 index 00000000..b2cddc5d --- /dev/null +++ b/styles/z-bolt/images/speed-17%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-34%.svg b/styles/z-bolt/images/speed-34%.svg new file mode 100644 index 00000000..69c3f69b --- /dev/null +++ b/styles/z-bolt/images/speed-34%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-50%.svg b/styles/z-bolt/images/speed-50%.svg new file mode 100644 index 00000000..839edb17 --- /dev/null +++ b/styles/z-bolt/images/speed-50%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-67%.svg b/styles/z-bolt/images/speed-67%.svg new file mode 100644 index 00000000..1ab657c9 --- /dev/null +++ b/styles/z-bolt/images/speed-67%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/speed-83%.svg b/styles/z-bolt/images/speed-83%.svg new file mode 100644 index 00000000..b1914012 --- /dev/null +++ b/styles/z-bolt/images/speed-83%.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 755470f88dbcf8f297cef290a8d8b5d43ec919d7 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:22:34 -0800 Subject: [PATCH 22/94] added additional speed dial images --- docs/ButtonImages.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/ButtonImages.html b/docs/ButtonImages.html index ee6b0165..59aa3132 100755 --- a/docs/ButtonImages.html +++ b/docs/ButtonImages.html @@ -227,9 +227,6 @@
shutdown
- - -
speed-0%
@@ -248,11 +245,6 @@
speed-100%
- - - - -
speed-fast
From 814b2a6befb11b8c8d7a53c9f35ebe911d834b3a Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 17 Jan 2021 14:43:49 -0800 Subject: [PATCH 23/94] added missing image --- docs/ButtonImages.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/ButtonImages.html b/docs/ButtonImages.html index 59aa3132..61ffbfdc 100755 --- a/docs/ButtonImages.html +++ b/docs/ButtonImages.html @@ -239,6 +239,9 @@
speed-50%
+ +
speed-67%
+
speed-83%
From 55fcfb2c8a23feab56a040a79c8ec6043078d75f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 17 Jan 2021 14:49:06 -0800 Subject: [PATCH 24/94] changed statusMapping to public --- .../github.com/mcuadros/go-octoprint/client.go | 16 ++++++++-------- .../mcuadros/go-octoprint/connection.go | 2 +- vendor/github.com/mcuadros/go-octoprint/files.go | 8 ++++---- vendor/github.com/mcuadros/go-octoprint/job.go | 2 +- .../github.com/mcuadros/go-octoprint/printer.go | 12 ++++++------ .../github.com/mcuadros/go-octoprint/system.go | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/vendor/github.com/mcuadros/go-octoprint/client.go b/vendor/github.com/mcuadros/go-octoprint/client.go index 6d3e259b..9e33d8e7 100755 --- a/vendor/github.com/mcuadros/go-octoprint/client.go +++ b/vendor/github.com/mcuadros/go-octoprint/client.go @@ -42,13 +42,13 @@ func NewClient(endpoint, apiKey string) *Client { } func (c *Client) doJSONRequest( - method, target string, body io.Reader, m statusMapping, + method, target string, body io.Reader, m StatusMapping, ) ([]byte, error) { return c.doRequest(method, target, "application/json", body, m) } func (c *Client) doJSONRequestWithLogging( - method, target string, body io.Reader, m statusMapping, + method, target string, body io.Reader, m StatusMapping, ) ([]byte, error) { return c.doRequestWithLogging(method, target, "application/json", body, m) } @@ -56,7 +56,7 @@ func (c *Client) doJSONRequestWithLogging( func (c *Client) doRequest( - method, target, contentType string, body io.Reader, m statusMapping, + method, target, contentType string, body io.Reader, m StatusMapping, ) ([]byte, error) { req, err := http.NewRequest(method, joinURL(c.Endpoint, target), body) if err != nil { @@ -83,7 +83,7 @@ func (c *Client) doRequest( func (c *Client) doRequestWithLogging( - method, target, contentType string, body io.Reader, m statusMapping, + method, target, contentType string, body io.Reader, m StatusMapping, ) ([]byte, error) { @@ -140,7 +140,7 @@ func (c *Client) doRequestWithLogging( -func (c *Client) handleResponse(r *http.Response, m statusMapping) ([]byte, error) { +func (c *Client) handleResponse(r *http.Response, m StatusMapping) ([]byte, error) { defer r.Body.Close() if m != nil { @@ -171,7 +171,7 @@ func (c *Client) handleResponse(r *http.Response, m statusMapping) ([]byte, erro -func (c *Client) handleResponseWithLogging(r *http.Response, m statusMapping) ([]byte, error) { +func (c *Client) handleResponseWithLogging(r *http.Response, m StatusMapping) ([]byte, error) { log.Println("Now in Client.handleResponse()") @@ -224,9 +224,9 @@ func joinURL(base, uri string) string { return b.ResolveReference(u).String() } -type statusMapping map[int]string +type StatusMapping map[int]string -func (m *statusMapping) Error(code int) error { +func (m *StatusMapping) Error(code int) error { err, ok := (*m)[code] if ok { return fmt.Errorf(err) diff --git a/vendor/github.com/mcuadros/go-octoprint/connection.go b/vendor/github.com/mcuadros/go-octoprint/connection.go index 0345ada1..809ccbd9 100755 --- a/vendor/github.com/mcuadros/go-octoprint/connection.go +++ b/vendor/github.com/mcuadros/go-octoprint/connection.go @@ -8,7 +8,7 @@ import ( const URIConnection = "/api/connection" -var ConnectionErrors = statusMapping{ +var ConnectionErrors = StatusMapping{ 400: "The selected port or baudrate for a connect command are not part of the available option", } diff --git a/vendor/github.com/mcuadros/go-octoprint/files.go b/vendor/github.com/mcuadros/go-octoprint/files.go index 73542af9..80664c2d 100755 --- a/vendor/github.com/mcuadros/go-octoprint/files.go +++ b/vendor/github.com/mcuadros/go-octoprint/files.go @@ -18,23 +18,23 @@ const ( ) var ( - FilesLocationGETErrors = statusMapping{ + FilesLocationGETErrors = StatusMapping{ 404: "Location is neither local nor sdcard", } - FilesLocationPOSTErrors = statusMapping{ + FilesLocationPOSTErrors = StatusMapping{ 400: "No file or foldername are included in the request, userdata was provided but could not be parsed as JSON or the request is otherwise invalid.", 404: "Location is neither local nor sdcard or trying to upload to SD card and SD card support is disabled", 409: "The upload of the file would override the file that is currently being printed or if an upload to SD card was requested and the printer is either not operational or currently busy with a print job.", 415: "The file is neither a gcode nor an stl file (or it is an stl file but slicing support is disabled)", 500: "The upload failed internally", } - FilesLocationPathPOSTErrors = statusMapping{ + FilesLocationPathPOSTErrors = StatusMapping{ 400: "The command is unknown or the request is otherwise invalid", 415: "A slice command was issued against something other than an STL file.", 404: "Location is neither local nor sdcard or the requested file was not found", 409: "Selected file is supposed to start printing directly but the printer is not operational or if a file to be sliced is supposed to be selected or start printing directly but the printer is not operational or already printing.", } - FilesLocationDeleteErrors = statusMapping{ + FilesLocationDeleteErrors = StatusMapping{ 404: "Location is neither local nor sdcard", 409: "The file to be deleted is currently being printed", } diff --git a/vendor/github.com/mcuadros/go-octoprint/job.go b/vendor/github.com/mcuadros/go-octoprint/job.go index cde0c232..27a093de 100755 --- a/vendor/github.com/mcuadros/go-octoprint/job.go +++ b/vendor/github.com/mcuadros/go-octoprint/job.go @@ -8,7 +8,7 @@ import ( ) -var JobToolErrors = statusMapping{ +var JobToolErrors = StatusMapping{ 409: "Printer is not operational or the current print job state does not match the preconditions for the command.", } diff --git a/vendor/github.com/mcuadros/go-octoprint/printer.go b/vendor/github.com/mcuadros/go-octoprint/printer.go index 8a3cde4b..01d05f09 100755 --- a/vendor/github.com/mcuadros/go-octoprint/printer.go +++ b/vendor/github.com/mcuadros/go-octoprint/printer.go @@ -20,21 +20,21 @@ const ( ) var ( - PrintErrors = statusMapping{ + PrintErrors = StatusMapping{ 409: "Printer is not operational", } - PrintHeadJobErrors = statusMapping{ + PrintHeadJobErrors = StatusMapping{ 400: "Invalid axis specified, invalid value for travel amount for a jog command or factor for feed rate or otherwise invalid request", 409: "Printer is not operational or currently printing", } - PrintToolErrors = statusMapping{ + PrintToolErrors = StatusMapping{ 400: "Targets or offsets contains a property or tool contains a value not matching the format tool{n}, the target/offset temperature, extrusion amount or flow rate factor is not a valid number or outside of the supported range, or if the request is otherwise invalid", 409: "Printer is not operational", } - PrintBedErrors = statusMapping{ + PrintBedErrors = StatusMapping{ 409: "Printer is not operational or the selected printer profile does not have a heated bed.", } - PrintSDErrors = statusMapping{ + PrintSDErrors = StatusMapping{ 404: "SD support has been disabled in OctoPrint’s settings.", 409: "SD card has not been initialized.", } @@ -657,7 +657,7 @@ func (cmd *SDReleaseRequest) Do(c *Client) error { // doCommandRequest can be used in any operation where the only required field // is the `command` field. -func doCommandRequest(c *Client, uri, command string, m statusMapping) error { +func doCommandRequest(c *Client, uri, command string, m StatusMapping) error { v := map[string]string{"command": command} b := bytes.NewBuffer(nil) diff --git a/vendor/github.com/mcuadros/go-octoprint/system.go b/vendor/github.com/mcuadros/go-octoprint/system.go index 0aaea5b5..a327db0b 100755 --- a/vendor/github.com/mcuadros/go-octoprint/system.go +++ b/vendor/github.com/mcuadros/go-octoprint/system.go @@ -5,7 +5,7 @@ import ( "fmt" ) -var ExecuteErrors = statusMapping{ +var ExecuteErrors = StatusMapping{ 404: "The command could not be found for source and action", 500: "The command didn’t define a command to execute, the command returned a non-zero return code and ignore was not true or some other internal server error occurred", } From 4e1682430b2960a2153b2a99989ac449bba0b563 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 23 Jan 2021 19:52:24 -0800 Subject: [PATCH 25/94] hard fork of the mcuadros/go-octoprint code into octoprintApis --- interfaces/ITemperatureDataDisplay.go | 4 +- octoprintApis/FileRequest.go | 136 +++ octoprintApis/FullStateRequest.go | 94 ++ octoprintApis/JobInformation.go | 33 + octoprintApis/JobRequest.go | 46 + octoprintApis/LICENSE | 21 + octoprintApis/PrinterProfilesRequest.go | 27 + octoprintApis/ProgressInformation.go | 29 + octoprintApis/README.md | 146 +++ octoprintApis/SelectFileRequest.go | 48 + octoprintApis/TemperatureData.go | 21 + octoprintApis/TemperatureStateResponse.go | 47 + octoprintApis/_examples/state/main.go | 40 + octoprintApis/client.go | 238 +++++ octoprintApis/common.go | 1029 +++++++++++++++++++++ octoprintApis/common_test.go | 176 ++++ octoprintApis/connection.go | 112 +++ octoprintApis/files.go | 250 +++++ octoprintApis/files_test.go | 86 ++ octoprintApis/job.go | 175 ++++ octoprintApis/plugin_manager.go | 76 ++ octoprintApis/printer.go | 670 ++++++++++++++ octoprintApis/printer_test.go | 97 ++ octoprintApis/settings.go | 23 + octoprintApis/settings_test.go | 17 + octoprintApis/system.go | 59 ++ octoprintApis/system_test.go | 31 + octoprintApis/version.go | 25 + octoprintApis/zbolt.go | 148 +++ ui/BedLevelPanel.go | 12 +- ui/CommonPanel.go | 6 +- ui/ControlPanel.go | 16 +- ui/CustomItemsPanel.go | 6 +- ui/FanPanel.go | 1 - ui/FilamentPanel.go | 1 - ui/FilesPanel.go | 44 +- ui/HomePanel.go | 8 +- ui/IdleStatusPanel.go | 6 +- ui/MovePanel.go | 28 +- ui/PrintStatusPanel.go | 20 +- ui/TemperaturePresetsPanel.go | 4 +- ui/menu.go | 9 +- ui/tool_changer_panel.go | 6 +- ui/ui.go | 23 +- ui/z_offset_calibration_panel.go | 12 +- uiWidgets/CommandButton.go | 14 +- uiWidgets/ControlButton.go | 12 +- uiWidgets/CoolDownButton.go | 12 +- uiWidgets/FanButton.go | 8 +- uiWidgets/FilamentExtrudeButton.go | 8 +- uiWidgets/FilamentLoadButton.go | 8 +- uiWidgets/FlowRateStepButton.go | 8 +- uiWidgets/HomeAllButton.go | 18 +- uiWidgets/HomeButton.go | 12 +- uiWidgets/IncreaseZOffsetButton.go | 1 - uiWidgets/MoveButton.go | 18 +- uiWidgets/OctoPrintInfoBox.go | 6 +- uiWidgets/OctoScreenInfoBox.go | 4 +- uiWidgets/OctoScreenPluginInfoBox.go | 6 +- uiWidgets/SelectToolStepButton.go | 4 +- uiWidgets/SystemCommandButton.go | 12 +- uiWidgets/SystemInfoBox.go | 4 +- uiWidgets/SystemInformationInfoBox.go | 2 - uiWidgets/TemperatureIncreaseButton.go | 6 +- uiWidgets/TemperaturePresetButton.go | 18 +- uiWidgets/TemperatureStatusBox.go | 10 +- uiWidgets/ToolButton.go | 14 +- uiWidgets/ToolPrintingButon.go | 1 - utils/FileResponsesSortedByDate.go | 6 +- utils/FileResponsesSortedByName.go | 6 +- utils/LocationHistory.go | 10 +- utils/UpdateTemperaturesBackgroundTask.go | 8 +- utils/tools.go | 26 +- utils/ui_utils.go | 4 +- 74 files changed, 4131 insertions(+), 241 deletions(-) create mode 100755 octoprintApis/FileRequest.go create mode 100755 octoprintApis/FullStateRequest.go create mode 100755 octoprintApis/JobInformation.go create mode 100755 octoprintApis/JobRequest.go create mode 100644 octoprintApis/LICENSE create mode 100644 octoprintApis/PrinterProfilesRequest.go create mode 100755 octoprintApis/ProgressInformation.go create mode 100644 octoprintApis/README.md create mode 100755 octoprintApis/SelectFileRequest.go create mode 100755 octoprintApis/TemperatureData.go create mode 100755 octoprintApis/TemperatureStateResponse.go create mode 100644 octoprintApis/_examples/state/main.go create mode 100755 octoprintApis/client.go create mode 100755 octoprintApis/common.go create mode 100644 octoprintApis/common_test.go create mode 100755 octoprintApis/connection.go create mode 100755 octoprintApis/files.go create mode 100644 octoprintApis/files_test.go create mode 100755 octoprintApis/job.go create mode 100755 octoprintApis/plugin_manager.go create mode 100755 octoprintApis/printer.go create mode 100755 octoprintApis/printer_test.go create mode 100755 octoprintApis/settings.go create mode 100644 octoprintApis/settings_test.go create mode 100755 octoprintApis/system.go create mode 100644 octoprintApis/system_test.go create mode 100644 octoprintApis/version.go create mode 100755 octoprintApis/zbolt.go diff --git a/interfaces/ITemperatureDataDisplay.go b/interfaces/ITemperatureDataDisplay.go index 2ae64363..9ac7c922 100755 --- a/interfaces/ITemperatureDataDisplay.go +++ b/interfaces/ITemperatureDataDisplay.go @@ -1,9 +1,9 @@ package interfaces import ( - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) type ITemperatureDataDisplay interface { - UpdateTemperatureData(temperatureData map[string]octoprint.TemperatureData) + UpdateTemperatureData(temperatureData map[string]octoprintApis.TemperatureData) } diff --git a/octoprintApis/FileRequest.go b/octoprintApis/FileRequest.go new file mode 100755 index 00000000..f87ba776 --- /dev/null +++ b/octoprintApis/FileRequest.go @@ -0,0 +1,136 @@ +package octoprintApis + +import ( + "fmt" + "encoding/json" + + // "log" + // "strconv" + // "strings" + // "time" + + // "../octoprint" +) + +// Retrieve a specific file’s or folder’s information +// GET /api/files/(string:location)/(path:filename) +// https://docs.octoprint.org/en/master/api/files.html#retrieve-a-specific-file-s-or-folder-s-information + + +// FileRequest retrieves the selected file’s or folder’s information. +type FileRequest struct { + // Location of the file for which to retrieve the information/ Can be either + // `local` or `sdcard`. + Location Location + + // Filename of the file for which to retrieve the information. + Filename string + + // Recursive if set to true, return all files and folders recursively. + // Otherwise only return items on same level. + Recursive bool +} + +// FileResponse contains information regarding a file. +// https://docs.octoprint.org/en/master/api/datamodel.html#file-information +type FileResponse struct { + // Name is name of the file without path. E.g. “file.gco” for a file + // “file.gco” located anywhere in the file system. + Name string `json:"name"` + + // The name of the file without the path. + Display string `json:"display"` + + // Path is the path to the file within the location. E.g. + //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” + // and “subfolder” relative to the root of the location. + Path string `json:"path"` + + // Type of file. model or machinecode. Or folder if it’s a folder, in + // which case the children node will be populated. + Type string `json:"type"` + + // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` + // for .stl files, or `["machinecode", "gcode"]` for .gcode files. + // `["folder"]` for folders. + TypePath []string `json:"typePath"` + + + + + // Additional properties depend on type. For a type value of folder, see Folders. For any other value see Files. + + // * Folders + // --children + // --size + + + + // * Files + // Hash is the MD5 hash of the file. Only available for `local` files. + Hash string `json:"hash"` + + // Size of the file in bytes. Only available for `local` files or `sdcard` + // files if the printer supports file sizes for sd card files. + Size uint64 `json:"size"` + + // Date when this file was uploaded. Only available for `local` files. + Date JSONTime `json:"date"` + + // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, + // `sdcard` when stored on the printer’s SD card (if available). + Origin string `json:"origin"` + + // Refs references relevant to this file, left out in abridged version. + Refs Reference `json:"refs"` + + // GCodeAnalysis information from the analysis of the GCODE file, if + // available. Left out in abridged version. + GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` + + + + + // * Additional properties not listed in the SDK... + + // Print information from the print stats of a file. + Print PrintStats `json:"print"` + + + // Relative path to the preview thumbnail image (if it exists) + // The PrusaSlicer Thumbnails plug-in is required or this. + Thumbnail string `json:"thumbnail"` +} + +// IsFolder it returns true if the file is a folder. +func (response *FileResponse) IsFolder() bool { + if len(response.TypePath) == 1 && response.TypePath[0] == "folder" { + return true + } + + return false +} + +const URIFiles = "/api/files" + +// Do sends an API request and returns the API response +func (request *FileRequest) Do(c *Client) (*FileResponse, error) { + uri := fmt.Sprintf("%s/%s/%s?recursive=%t", + URIFiles, + request.Location, + request.Filename, + request.Recursive, + ) + + bytes, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) + if err != nil { + return nil, err + } + + response := &FileResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/FullStateRequest.go b/octoprintApis/FullStateRequest.go new file mode 100755 index 00000000..90112605 --- /dev/null +++ b/octoprintApis/FullStateRequest.go @@ -0,0 +1,94 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + "log" + "strings" +) + +// FullStateRequest retrieves the current state of the printer. +type FullStateRequest struct { + // bytes if true retrieve the temperature history. + IncludeHistory bool + + // Limit limits the amount of returned history data points. + Limit int + + // Exclude list of fields to exclude from the response (e.g. if not + // needed by the client). Valid values to supply here are `temperature`, + // `sd` and `state`. + Exclude []string +} + +// FullStateResponse contains informantion about the current state of the printer. +type FullStateResponse struct { + // TemperatureStateResponse is the printer’s temperature state data. + Temperature TemperatureStateResponse `json:"temperature"` + + // SD is the printer’s sd state data. + SD SDState `json:"sd"` + + // State is the printer’s general state. + State PrinterState `json:"state"` +} + +const URIPrinter = "/api/printer" + +// Do sends an API request and returns the API response. +func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { + uri := fmt.Sprintf( + "%s?history=%t&limit=%d&exclude=%s", + URIPrinter, + cmd.IncludeHistory, + cmd.Limit, + strings.Join(cmd.Exclude, ","), + ) + + log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) + //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state + /* + { + "temperature": { + "bed": { + "actual": 26.9, + "offset": 0, + "target": 0.0 + }, + "history": [ + { + "bed": { + "actual": 26.9, + "target": 0.0 + }, + "time": 1598235178, + "tool0": { + "actual": 35.4, + "target": 0.0 + } + } + ], + "tool0": { + "actual": 35.4, + "offset": 0, + "target": 0.0 + } + } + } + */ + + + bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) + if err != nil { + return nil, err + } + + response := &FullStateResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/JobInformation.go b/octoprintApis/JobInformation.go new file mode 100755 index 00000000..3b3ec892 --- /dev/null +++ b/octoprintApis/JobInformation.go @@ -0,0 +1,33 @@ +package octoprintApis + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// Job information +// https://docs.octoprint.org/en/master/api/datamodel.html#job-information + + +// JobInformation contains information regarding the target of the current job. +type JobInformation struct { + // File is the file that is the target of the current print job. + File FileResponse `json:"file"` + + // EstimatedPrintTime is the estimated print time for the file, in seconds. + EstimatedPrintTime float64 `json:"estimatedPrintTime"` + + // LastPrintTime is the print time of the last print of the file, in seconds. + LastPrintTime float64 `json:"lastPrintTime"` + + // Filament contains Information regarding the estimated filament usage of the print job. + Filament struct { + // Length of filament used, in mm + Length float64 `json:"length"` + + // Volume of filament used, in cm³ + Volume float64 `json:"volume"` + } `json:"filament"` +} diff --git a/octoprintApis/JobRequest.go b/octoprintApis/JobRequest.go new file mode 100755 index 00000000..23797551 --- /dev/null +++ b/octoprintApis/JobRequest.go @@ -0,0 +1,46 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + // "io" + // "log" +) + +// JobRequest retrieve information about the current job (if there is one). +type JobRequest struct{} + + + +// Job information response +// https://docs.octoprint.org/en/master/api/job.html#job-information-response + +// JobResponse is the response from a job command. +type JobResponse struct { + // Job contains information regarding the target of the current print job. + Job JobInformation `json:"job"` + + // Progress contains information regarding the progress of the current job. + Progress ProgressInformation `json:"progress"` + + //State StateInformation `json:"state"` + State string `json:"state"` +} + +// https://docs.octoprint.org/en/master/api/job.html +const JobTool = "/api/job" + +// Do sends an API request and returns the API response. +func (cmd *JobRequest) Do(client *Client) (*JobResponse, error) { + bytes, err := client.doJSONRequest("GET", JobTool, nil, nil) + if err != nil { + return nil, err + } + + response := &JobResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/LICENSE b/octoprintApis/LICENSE new file mode 100644 index 00000000..70377d09 --- /dev/null +++ b/octoprintApis/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Máximo Cuadros + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/octoprintApis/PrinterProfilesRequest.go b/octoprintApis/PrinterProfilesRequest.go new file mode 100644 index 00000000..74fc19bb --- /dev/null +++ b/octoprintApis/PrinterProfilesRequest.go @@ -0,0 +1,27 @@ +package octoprintApis + +import ( + "encoding/json" + "fmt" +) + +// SettingsRequest retrieves the current configuration of OctoPrint. +type PrinterProfilesRequest struct { + Id string +} + +// Do sends an API request and returns the API response. +func (cmd *PrinterProfilesRequest) Do(c *Client) (*PrinterProfile, error) { + uri := fmt.Sprintf("/api/printerprofiles/%s", cmd.Id) + b, err := c.doJSONRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + + r := &PrinterProfile{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/ProgressInformation.go b/octoprintApis/ProgressInformation.go new file mode 100755 index 00000000..194b5fb2 --- /dev/null +++ b/octoprintApis/ProgressInformation.go @@ -0,0 +1,29 @@ +package octoprintApis + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// Progress information +// https://docs.octoprint.org/en/master/api/datamodel.html#progress-information + +// ProgressInformation contains information regarding the progress of the current print job. +type ProgressInformation struct { + // Completion percentage of completion of the current print job. + Completion float64 `json:"completion"` + + // FilePosition current position in the file being printed, in bytes from the beginning. + FilePosition uint64 `json:"filepos"` + + // PrintTime is time already spent printing, in seconds. + PrintTime float64 `json:"printTime"` + + // PrintTimeLeft is estimate of time left to print, in seconds. + PrintTimeLeft float64 `json:"printTimeLeft"` + + // Origin of the current time left estimate. + PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` +} diff --git a/octoprintApis/README.md b/octoprintApis/README.md new file mode 100644 index 00000000..771e6300 --- /dev/null +++ b/octoprintApis/README.md @@ -0,0 +1,146 @@ +go-octoprint [![Build Status](https://travis-ci.org/mcuadros/go-octoprint.svg?branch=master)](https://travis-ci.org/mcuadros/go-octoprint) [![GoDoc](http://godoc.org/github.com/mcuadros/go-octoprint?status.svg)](http://godoc.org/github.com/mcuadros/go-octoprint) +============================== + +Go library for accessing the [OctoPrint](http://octoprint.org/)'s [REST API](http://docs.octoprint.org/en/master/api/index.html). + +Installation +------------ + +The recommended way to install go-octoprint + +``` +go get github.com/mcuadros/go-octoprint +``` + +Example +------- + +### Retrieving the current connection state: + +```go +client, _ := NewClient("", "") + +r := octoprint.ConnectionRequest{} +s, err := r.Do(client) +if err != nil { + log.Error("error requesting connection state: %s", err) +} + +fmt.Printf("Connection State: %q\n", s.Current.State) +``` + + +### Retrieving current temperature for bed and extruders: + +```go +r := octoprint.StateRequest{} +s, err := r.Do(c) +if err != nil { + log.Error("error requesting state: %s", err) +} + +fmt.Println("Current Temperatures:") +for tool, state := range s.Temperature.Current { + fmt.Printf("- %s: %.1f°C / %.1f°C\n", tool, state.Actual, state.Target) +} +``` + +## Implemented Methods + +### [Version Information](http://docs.octoprint.org/en/master/api/version.html) +- [x] GET `/api/version` + +### [Apps](http://docs.octoprint.org/en/master/api/apps.html) +- [ ] GET `/apps/auth` +- [ ] POST `/apps/auth` + +### [Connection Operations](http://docs.octoprint.org/en/master/api/connection.html) +- [x] GET `/api/connection` +- [x] POST `/api/connection` + +### [File Operations](http://docs.octoprint.org/en/master/api/files.html) +- [x] GET `/api/files +- [x] GET `/api/files/` +- [x] POST `/api/files/` +- [x] GET `/api/files//` +- [x] POST `/api/files//` (Only select command) +- [x] DELETE `/api/files//` + +### [Job Operations](http://docs.octoprint.org/en/master/api/job.html) +- [x] POST `/api/job` +- [x] GET `/api/job` + +### [Languages](http://docs.octoprint.org/en/master/api/languages.html) +- [ ] GET `/api/languages` +- [ ] POST `/api/languages` +- [ ] DELETE `/api/languages//` + +### [Log file management](http://docs.octoprint.org/en/master/api/logs.html) +- [ ] GET `/api/logs` +- [ ] DELETE `/api/logs/` + +### [Printer Operations](http://docs.octoprint.org/en/master/api/printer.html) +- [x] GET `/api/printer` +- [x] POST `/api/printer/printhead` +- [x] POST `/api/printer/tool` +- [x] GET `/api/printer/tool` +- [x] POST `/api/printer/bed` +- [x] GET `/api/printer/bed` +- [x] POST `/api/printer/sd` +- [x] GET `/api/printer/sd` +- [x] POST `/api/printer/command` +- [x] GET `/api/printer/command/custom` ([un-documented at REST API](https://github.com/foosel/OctoPrint/blob/7f5d03d0549bcbd26f40e7e4a3297ea5204fb1cc/src/octoprint/server/api/printer.py#L376)) + +### [Printer profile operations](http://docs.octoprint.org/en/master/api/printerprofiles.html) +- [ ] GET `/api/printerprofiles` +- [ ] POST `/api/printerprofiles` +- [ ] PATCH `/api/printerprofiles/` +- [ ] DELETE `/api/printerprofiles/` + +### [Settings](http://docs.octoprint.org/en/master/api/settings.html) +- [x] GET `/api/settings` +- [ ] POST `/api/settings` +- [ ] POST `/api/settings/apikey` + +### [Slicing](http://docs.octoprint.org/en/master/api/slicing.html) +- [ ] GET `/api/slicing` +- [ ] GET `/api/slicing//profiles` +- [ ] GET `/api/slicing//profiles/` +- [ ] PUT `/api/slicing//profiles/` +- [ ] DELETE `/api/slicing//profiles/` + +### [System](http://docs.octoprint.org/en/master/api/system.html) +- [x] GET `/api/system/commands` +- [ ] GET `/api/system/commands/` +- [x] POST `/api/system/commands//` + +### [Timelapse](http://docs.octoprint.org/en/master/api/timelapse.html) +- [ ] GET `/api/timelapse` +- [ ] DELETE `/api/timelapse/` +- [ ] POST `/api/timelapse/unrendered/` +- [ ] DELETE `/api/timelapse/unrendered/` +- [ ] POST `/api/timelapse` + +### [User](http://docs.octoprint.org/en/master/api/users.html) +- [ ] GET `/api/users` +- [ ] GET `/api/users/` +- [ ] POST `/api/users` +- [ ] PUT `/api/users/` +- [ ] DELETE `/api/users/` +- [ ] PUT `/api/users//password` +- [ ] GET `/api/users//settings` +- [ ] PATCH `/api/users//settings` +- [ ] POST `/api/users//apikey` +- [ ] DELETE `/api/users//apikey` + +### [Util](http://docs.octoprint.org/en/master/api/util.html) +- [ ] POST `/api/util/test` + +### [Wizard](http://docs.octoprint.org/en/master/api/wizard.html) +- [ ] GET `/setup/wizard` +- [ ] POST `/setup/wizard` + +License +------- + +MIT, see [LICENSE](LICENSE) diff --git a/octoprintApis/SelectFileRequest.go b/octoprintApis/SelectFileRequest.go new file mode 100755 index 00000000..fabb9135 --- /dev/null +++ b/octoprintApis/SelectFileRequest.go @@ -0,0 +1,48 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + // "mime/multipart" +) + +// SelectFileRequest selects a file for printing. +type SelectFileRequest struct { + // Location is target location on which to send the command for is located, + // either local (for OctoPrint’s uploads folder) or sdcard for the + // printer’s SD card (if available). + Location Location `json:"-"` + + // Path of the file for which to issue the command. + Path string `json:"-"` + + // Print, if set to true the file will start printing directly after + // selection. If the printer is not operational when this parameter is + // present and set to true, the request will fail with a response of + // 409 Conflict. + Print bool `json:"print"` +} + +// Do sends an API request and returns an error if any. +func (cmd *SelectFileRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) + _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) + return err +} + +func (cmd *SelectFileRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + SelectFileRequest + }{ + Command: "select", + SelectFileRequest: *cmd, + }) +} diff --git a/octoprintApis/TemperatureData.go b/octoprintApis/TemperatureData.go new file mode 100755 index 00000000..1bc948e5 --- /dev/null +++ b/octoprintApis/TemperatureData.go @@ -0,0 +1,21 @@ +package octoprintApis + +import ( + // "encoding/json" + // "strconv" + // "strings" + // "time" +) + +// TemperatureData is temperature stats for a tool. +type TemperatureData struct { + // Actual current temperature. + Actual float64 `json:"actual"` + + // Target temperature, may be nil if no target temperature is set. + Target float64 `json:"target"` + + // Offset currently configured temperature offset to apply, will be left + // out for historic temperature information. + Offset float64 `json:"offset"` +} diff --git a/octoprintApis/TemperatureStateResponse.go b/octoprintApis/TemperatureStateResponse.go new file mode 100755 index 00000000..40754aa1 --- /dev/null +++ b/octoprintApis/TemperatureStateResponse.go @@ -0,0 +1,47 @@ +package octoprintApis + +import ( + "encoding/json" + // "strconv" + // "strings" + // "time" +) + + +// TODO: add request +// TODO: add Do() + + +// TemperatureState is the printer’s temperature state data. +type TemperatureStateResponse temperatureStateResponse + +type temperatureStateResponse struct { + // Current temperature stats. + CurrentTemperatureData map[string]TemperatureData `json:"current"` + + // Temperature history. + History []*HistoricTemperatureData `json:"history"` +} + +func (r *TemperatureStateResponse) UnmarshalJSON(bytes []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(bytes, &raw); err != nil { + return err + } + + history := raw["history"] + delete(raw, "history") + bytes, _ = json.Marshal(map[string]interface{}{ + "current": raw, + "history": history, + }) + + i := &temperatureStateResponse{} + if err := json.Unmarshal(bytes, i); err != nil { + return err + } + + *r = TemperatureStateResponse(*i) + + return nil +} diff --git a/octoprintApis/_examples/state/main.go b/octoprintApis/_examples/state/main.go new file mode 100644 index 00000000..0d30df2b --- /dev/null +++ b/octoprintApis/_examples/state/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "os" + + "github.com/mgutz/logxi/v1" + "github.com/Z-Bolt/OctoScreen/octoprintApis" +) + +func main() { + baseURL, apiKey := os.Args[1], os.Args[2] + + c := octoprintApis.NewClient(baseURL, apiKey) + printConnectionState(c) + printTemperature(c) +} + +func printConnectionState(c *octoprintApis.Client) { + r := octoprintApis.ConnectionRequest{} + s, err := r.Do(c) + if err != nil { + log.Error("error requesting connection state: %s", err) + } + + fmt.Printf("Connection State: %q\n", s.Current.State) +} + +func printTemperature(c *octoprintApis.Client) { + r := octoprintApis.StateRequest{} + s, err := r.Do(c) + if err != nil { + log.Error("error requesting state: %s", err) + } + + fmt.Println("Current Temperatures:") + for tool, state := range s.Temperature.Current { + fmt.Printf("- %s: %.1f°C / %.1f°C\n", tool, state.Actual, state.Target) + } +} diff --git a/octoprintApis/client.go b/octoprintApis/client.go new file mode 100755 index 00000000..c5a55ab8 --- /dev/null +++ b/octoprintApis/client.go @@ -0,0 +1,238 @@ +package octoprintApis + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" + "time" +) + +// ErrUnauthorized missing or invalid API key +var ErrUnauthorized = errors.New("Missing or invalid API key") + +// A Client manages communication with the OctoPrint API. +type Client struct { + // Endpoint address to the OctoPrint REST API server. + Endpoint string + + // APIKey used to connect to the OctoPrint REST API server. + APIKey string + + // TODO: + c *http.Client +} + +// NewClient returns a new OctoPrint API client with provided base URL and API +// Key. If baseURL does not have a trailing slash, one is added automatically. If +// `Access Control` is enabled at OctoPrint configuration an apiKey should be +// provided (http://docs.octoprint.org/en/master/api/general.html#authorization). +func NewClient(endpoint, apiKey string) *Client { + return &Client{ + Endpoint: endpoint, + APIKey: apiKey, + c: &http.Client{ + Timeout: time.Second * 3, + Transport: &http.Transport{ + DisableKeepAlives: true, + }, + }, + } +} + +func (c *Client) doJSONRequest( + method, target string, body io.Reader, m StatusMapping, +) ([]byte, error) { + return c.doRequest(method, target, "application/json", body, m) +} + +func (c *Client) doJSONRequestWithLogging( + method, target string, body io.Reader, m StatusMapping, +) ([]byte, error) { + return c.doRequestWithLogging(method, target, "application/json", body, m) +} + + + +func (c *Client) doRequest( + method, target, contentType string, body io.Reader, m StatusMapping, +) ([]byte, error) { + req, err := http.NewRequest(method, joinURL(c.Endpoint, target), body) + if err != nil { + return nil, err + } + + req.Header.Add("Host", "localhost:5000") + req.Header.Add("Accept", "*/*") + req.Header.Add("User-Agent", fmt.Sprintf("go-octoprint/%s", Version)) + if contentType != "" { + req.Header.Add("Content-Type", contentType) + } + + req.Header.Add("X-Api-Key", c.APIKey) + resp, err := c.c.Do(req) + if err != nil { + return nil, err + } + + return c.handleResponse(resp, m) +} + + + + +func (c *Client) doRequestWithLogging( + method, target, contentType string, body io.Reader, m StatusMapping, +) ([]byte, error) { + + + log.Println("Now in Client.doRequest()") + + + + req, err := http.NewRequest(method, joinURL(c.Endpoint, target), body) + if err != nil { + log.Println("Client.doRequest() - NewRequest() failed") + return nil, err + } + + req.Header.Add("Host", "localhost:5000") + req.Header.Add("Accept", "*/*") + req.Header.Add("User-Agent", fmt.Sprintf("go-octoprint/%s", Version)) + if contentType != "" { + req.Header.Add("Content-Type", contentType) + } + + req.Header.Add("X-Api-Key", c.APIKey) + + + resp, err := c.c.Do(req) + // resp, err := c.c.DoWithLogging(req) + if err != nil { + log.Println("Client.doRequest() - c.c.Do() failed") + return nil, err + } + + + + + + log.Println("!!! Now in Client.doRequest() - finished calling DoWithLogging() !!!") + if resp != nil { + log.Printf("!!! Now in Client.doRequest() - resp.Status: %s", resp.Status) + log.Printf("!!! Now in Client.doRequest() - resp.StatusCode: %d", resp.StatusCode) + } else { + log.Printf("!!! Now in Client.doRequest() - resp was nil") + } + + if err != nil { + log.Printf("!!! Now in Client.doRequest() - err: %s", err.Error()) + } else { + log.Printf("!!! Now in Client.doRequest() - err was nil") + } + return nil, err + + + + // return c.handleResponseWithLogging(resp, m) +} + + + +func (c *Client) handleResponse(r *http.Response, m StatusMapping) ([]byte, error) { + defer r.Body.Close() + + if m != nil { + if err := m.Error(r.StatusCode); err != nil { + return nil, err + } + } + + if r.StatusCode == 401 { + return nil, ErrUnauthorized + } + + if r.StatusCode == 204 { + return nil, nil + } + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + + if r.StatusCode >= 200 && r.StatusCode <= 209 { + return body, nil + } + + return nil, fmt.Errorf("unexpected status code: %d", r.StatusCode) +} + + + +func (c *Client) handleResponseWithLogging(r *http.Response, m StatusMapping) ([]byte, error) { + + log.Println("Now in Client.handleResponse()") + + defer r.Body.Close() + + if m != nil { + log.Println("Client.handleResponse() - m is nil") + + if err := m.Error(r.StatusCode); err != nil { + log.Println("Client.handleResponse() - m.Error is not nil and is: ", err) + log.Println("Client.handleResponse() - r.StatusCode: ", r.StatusCode) + return nil, err + } + } + + if r.StatusCode == 401 { + log.Println("Client.handleResponse() - status code is 401, returning") + return nil, ErrUnauthorized + } + + if r.StatusCode == 204 { + log.Println("Client.handleResponse() - status code is 204, returning") + return nil, nil + } + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Println("Client.handleResponse() - ReadAll() failed, err is: ", err) + return nil, err + } + + if r.StatusCode >= 200 && r.StatusCode <= 209 { + log.Println("Client.handleResponse() - status code appears to be good, returning") + return body, nil + } + + log.Println("Client.handleResponse() - looks like it failed, status code was ", r.StatusCode) + + + return nil, fmt.Errorf("unexpected status code: %d", r.StatusCode) +} + + + + + +func joinURL(base, uri string) string { + u, _ := url.Parse(uri) + b, _ := url.Parse(base) + return b.ResolveReference(u).String() +} + +type StatusMapping map[int]string + +func (m *StatusMapping) Error(code int) error { + err, ok := (*m)[code] + if ok { + return fmt.Errorf(err) + } + + return nil +} diff --git a/octoprintApis/common.go b/octoprintApis/common.go new file mode 100755 index 00000000..758e8e40 --- /dev/null +++ b/octoprintApis/common.go @@ -0,0 +1,1029 @@ +package octoprintApis + +import ( + "encoding/json" + "strconv" + "strings" + "time" +) + +var Version = "0.1" + +type Axis string + +const ( + XAxis Axis = "x" + YAxis Axis = "y" + ZAxis Axis = "z" +) + +// JobResponse is now in JobRequest.go +// // JobResponse is the response from a job command. +// type JobResponse struct { +// // Job contains information regarding the target of the current print job. +// Job JobInformation `json:"job"` + +// // Progress contains information regarding the progress of the current job. +// Progress ProgressInformation `json:"progress"` + +// //State StateInformation `json:"state"` +// State string `json:"state"` +// } + + + +// JobInformation i no in JobInformation.go +// // JobInformation contains information regarding the target of the current job. +// type JobInformation struct { +// // File is the file that is the target of the current print job. +// File FileResponse `json:"file"` + +// // EstimatedPrintTime is the estimated print time for the file, in seconds. +// EstimatedPrintTime float64 `json:"estimatedPrintTime"` + +// // LastPrintTime is the print time of the last print of the file, in seconds. +// LastPrintTime float64 `json:"lastPrintTime"` + +// // Filament contains Information regarding the estimated filament +// // usage of the print job. +// Filament struct { +// // Length of filament used, in mm +// Length float64 `json:"length"` +// // Volume of filament used, in cm³ +// Volume float64 `json:"volume"` +// } `json:"filament"` + +// FilePosition uint64 `json:"filepos"` +// } + + + +// ProgressInformation is now in ProgressInformation.go +// ProgressInformation contains information regarding the progress of the +// current print job. +// type ProgressInformation struct { +// // Completion percentage of completion of the current print job. +// Completion float64 `json:"completion"` + +// // FilePosition current position in the file being printed, in bytes +// // from the beginning. +// FilePosition uint64 `json:"filepos"` + +// // PrintTime is time already spent printing, in seconds +// PrintTime float64 `json:"printTime"` + +// // PrintTimeLeft is estimate of time left to print, in seconds +// PrintTimeLeft float64 `json:"printTimeLeft"` + +// // Origin of the current time left estimate +// PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` +// } + + + + +// TemperatureStateResponse is now in TemperatureStateResponse.go +// // TemperatureState is the printer’s temperature state data. +// type TemperatureStateResponse temperatureStateResponse + +// type temperatureStateResponse struct { +// // Current temperature stats. +// CurrentTemperatureData map[string]TemperatureData `json:"current"` + +// // Temperature history. +// History []*HistoricTemperatureData `json:"history"` +// } + +// func (r *TemperatureStateResponse) UnmarshalJSON(b []byte) error { +// var raw map[string]interface{} +// if err := json.Unmarshal(b, &raw); err != nil { +// return err +// } + +// history := raw["history"] +// delete(raw, "history") +// b, _ = json.Marshal(map[string]interface{}{ +// "current": raw, +// "history": history, +// }) + +// i := &temperatureStateResponse{} +// if err := json.Unmarshal(b, i); err != nil { +// return err +// } + +// *r = TemperatureStateResponse(*i) +// return nil +// } + +// TemperatureData is now in TemperatureData.go +// // TemperatureData is temperature stats for a tool. +// type TemperatureData struct { +// // Actual current temperature. +// Actual float64 `json:"actual"` + +// // Target temperature, may be nil if no target temperature is set. +// Target float64 `json:"target"` + +// // Offset currently configured temperature offset to apply, will be left +// // out for historic temperature information. +// Offset float64 `json:"offset"` +// } + +// PrinterState current state of the printer. +type PrinterState struct { + Text string `json:"text"` + Flags struct { + Operations bool `json:"operational"` + Paused bool `json:"paused"` + Printing bool `json:"printing"` + SDReady bool `json:"sdReady"` + Error bool `json:"error"` + Ready bool `json:"ready"` + ClosedOnError bool `json:"closedOrError"` + } `json:"flags"` +} + +// SDState is the state of the sd reader. +type SDState struct { + Ready bool `json:"ready"` +} + +// HistoricTemperatureData is temperature historic stats for a tool. +type HistoricTemperatureData historicTemperatureData +type historicTemperatureData struct { + // Time of this data point. + Time JSONTime `json:"time"` + + // Tools is temperature stats a set of tools. + Tools map[string]TemperatureData `json:"tools"` +} + +func (h *HistoricTemperatureData) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + + ts := raw["time"] + delete(raw, "time") + b, _ = json.Marshal(map[string]interface{}{ + "time": ts, + "tools": raw, + }) + + i := &historicTemperatureData{} + if err := json.Unmarshal(b, i); err != nil { + return err + } + + *h = HistoricTemperatureData(*i) + return nil +} + +// VersionResponse is the response from a job command. +type VersionResponse struct { + // API is the API version. + API string `json:"api"` + + // Server is the server version. + Server string `json:"server"` +} + +type ConnectionState string + +const ( + Operational ConnectionState = "Operational" +) + +// The states are based on: +// https://github.com/foosel/OctoPrint/blob/77753ca02602d3a798d6b0a22535e6fd69ff448a/src/octoprint/util/comm.py#L549 + +func (s ConnectionState) IsOperational() bool { + return strings.HasPrefix(string(s), "Operational") +} + +func (s ConnectionState) IsPrinting() bool { + return strings.HasPrefix(string(s), "Printing") || + strings.HasPrefix(string(s), "Starting") || + strings.HasPrefix(string(s), "Sending") || + strings.HasPrefix(string(s), "Paused") || + strings.HasPrefix(string(s), "Pausing") || + strings.HasPrefix(string(s), "Transfering") +} + +func (s ConnectionState) IsOffline() bool { + return strings.HasPrefix(string(s), "Offline") || + strings.HasPrefix(string(s), "Closed") +} + +func (s ConnectionState) IsError() bool { + return strings.HasPrefix(string(s), "Error") || + strings.HasPrefix(string(s), "Unknown") +} + +func (s ConnectionState) IsConnecting() bool { + return strings.HasPrefix(string(s), "Opening") || + strings.HasPrefix(string(s), "Detecting") || + strings.HasPrefix(string(s), "Connecting") || + strings.HasPrefix(string(s), "Detecting") +} + +// ConnectionResponse is the response from a connection command. +type ConnectionResponse struct { + Current struct { + // State current state of the connection. + State ConnectionState `json:"state"` + + // Port to connect to. + Port string `json:"port"` + + // BaudRate speed of the connection. + BaudRate int `json:"baudrate"` + + // PrinterProfile profile to use for connection. + PrinterProfile string `json:"printerProfile"` + } + + Options struct { + // Ports list of available ports. + Ports []string `json:"ports"` + + // BaudRates list of available speeds. + BaudRates []int `json:"baudrates"` + + // PrinterProfile list of available profiles. + PrinterProfiles []*Profile `json:"printerProfiles"` + + // PortPreference default port. + PortPreference string `json:"portPreference"` + + // BaudRatePreference default speed. + BaudRatePreference int `json:"baudratePreference"` + + // PrinterProfilePreference default profile. + PrinterProfilePreference string `json:"printerProfilePreference"` + + // Autoconnect whether to automatically connect to the printer on + // OctoPrint’s startup in the future. + Autoconnect bool `json:"autoconnect"` + } +} + +// Profile describe a printer profile. +type Profile struct { + // ID is the identifier of the profile. + ID string `json:"id"` + + // Name is the display name of the profile. + Name string `json:"name"` +} + +// FilesResponse is the response to a FilesRequest. +type FilesResponse struct { + // Files is the list of requested files. Might be an empty list if no files + // are available + Files []*FileResponse + Children []*FileResponse + + // Free is the amount of disk space in bytes available in the local disk + // space (refers to OctoPrint’s `uploads` folder). Only returned if file + // list was requested for origin `local` or all origins. + Free uint64 +} + +// FileInformation/FileResponse is now in FileRequest.go +// TODO: remove this commented code +// FileInformation contains information regarding a file. +// type FileInformation struct { +// // Name is name of the file without path. E.g. “file.gco” for a file +// // “file.gco” located anywhere in the file system. +// Name string `json:"name"` + +// // The name of the file without the path +// Display string `json:"display"` + +// // Path is the path to the file within the location. E.g. +// //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” +// // and “subfolder” relative to the root of the location. +// Path string `json:"path"` + +// // Type of file. model or machinecode. Or folder if it’s a folder, in +// // which case the children node will be populated. +// Type string `json:"type"` + +// // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` +// // for .stl files, or `["machinecode", "gcode"]` for .gcode files. +// // `["folder"]` for folders. +// TypePath []string `json:"typePath"` + +// // Hash is the MD5 hash of the file. Only available for `local` files. +// Hash string `json:"hash"` + +// // Size of the file in bytes. Only available for `local` files or `sdcard` +// // files if the printer supports file sizes for sd card files. +// Size uint64 `json:"size"` + +// // Date when this file was uploaded. Only available for `local` files. +// Date JSONTime `json:"date"` + +// // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, +// // `sdcard` when stored on the printer’s SD card (if available) +// Origin string `json:"origin"` + +// // Refs references relevant to this file, left out in abridged versio +// Refs Reference `json:"refs"` + +// // GCodeAnalysis information from the analysis of the GCODE file, if +// // available. Left out in abridged version. +// GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` + +// // Print information from the print stats of a file. +// Print PrintStats `json:"print"` +// } + +// // IsFolder it returns true if the file is a folder. +// func (f *FileInformation) IsFolder() bool { +// if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { +// return true +// } + +// return false +// } + +// Reference of a file. +type Reference struct { + // Resource that represents the file or folder (e.g. for issuing commands + // to or for deleting) + Resource string `json:"resource"` + + // Download URL for the file. Never present for folders. + Download string `json:"download"` + + // Model from which this file was generated (e.g. an STL, currently not + // used). Never present for folders. + Model string `json:"model"` +} + +// GCodeAnalysisInformation Information from the analysis of the GCODE file. +type GCodeAnalysisInformation struct { + // EstimatedPrintTime is the estimated print time of the file, in seconds. + EstimatedPrintTime float64 `json:"estimatedPrintTime"` + + // Filament estimated usage of filament + Filament struct { + // Length estimated of filament used, in mm + Length uint32 `json:"length"` + + // Volume estimated of filament used, in cm³ + Volume float64 `json:"volume"` + } `json:"filament"` +} + +// PrintStats information from the print stats of a file. +type PrintStats struct { + // Failure number of failed prints. + Failure int `json:"failure"` + + // Success number of success prints. + Success int `json:"success"` + + // Last print information. + Last struct { + // Date of the last print. + Date JSONTime `json:"date"` + + // Success or not. + Success bool `json:"success"` + } `json:"last"` +} + +// UploadFileResponse is the response to a UploadFileRequest. +type UploadFileResponse struct { + // Abridged information regarding the file that was just uploaded. If only + // uploaded to local this will only contain the local property. If uploaded + // to SD card, this will contain both local and sdcard properties. Only + // contained if a file was uploaded, not present if only a new folder was + // created. + File struct { + // Local is the information regarding the file that was just uploaded + // to the local storage. + Local *FileResponse `json:"local"` + + // SDCard is the information regarding the file that was just uploaded + // to the printer’s SD card. + SDCard *FileResponse `json:"sdcard"` + } `json:"files"` + + // Done whether any file processing after upload has already finished or + // not, e.g. due to first needing to perform a slicing step. Clients may + // use this information to direct progress displays related to the upload. + Done bool `json:"done"` +} + +// SystemCommandsResponse is the response to a SystemCommandsRequest. +type SystemCommandsResponse struct { + Core []*CommandDefinition `json:"core"` + Custom []*CommandDefinition `json:"custom"` +} + +// CommandSource is the source of the command definition. +type CommandSource string + +const ( + // Core for system actions defined by OctoPrint itself. + Core CommandSource = "core" + + // Custom for custom system commands defined by the user through `config.yaml`. + Custom CommandSource = "custom" +) + +// CommandDefinition describe a system command. +type CommandDefinition struct { + // Name of the command to display in the System menu. + Name string `json:"name"` + + // Command is the full command line to execute for the command. + Command string `json:"command"` + + // Action is an identifier to refer to the command programmatically. The + // special `action` string divider signifies a `divider` in the menu. + Action string `json:"action"` + + // Confirm if present and set, this text will be displayed to the user in a + // confirmation dialog they have to acknowledge in order to really execute + // the command. + RawConfirm json.RawMessage `json:"confirm"` + Confirm string `json:"-"` + + // Async whether to execute the command asynchronously or wait for its + // result before responding to the HTTP execution request. + Async bool `json:"async"` + + // Ignore whether to ignore the return code of the command’s execution. + Ignore bool `json:"ignore"` + + // Source of the command definition. + Source CommandSource `json:"source"` + + // Resource is the URL of the command to use for executing it. + Resource string `json:"resource"` +} + +type JSONTime struct{ time.Time } + +func (t JSONTime) MarshalJSON() ([]byte, error) { + return []byte(strconv.FormatInt(time.Time(t.Time).Unix(), 10)), nil +} + +func (t *JSONTime) UnmarshalJSON(s []byte) (err error) { + r := strings.Replace(string(s), `"`, ``, -1) + if r == "null" { + return nil + } + + q, err := strconv.ParseInt(r, 10, 64) + if err != nil { + return err + } + + t.Time = time.Unix(q, 0) + return +} + +// CustomCommandsResponse is the response to a CustomCommandsRequest. +type CustomCommandsResponse struct { + Controls []*ControlContainer `json:"controls"` +} + +// ControlContainer describes a control container. +type ControlContainer struct { + // Name to display above the container, basically a section header. + Name string `json:"name"` + + // Gcode command + Command string `json:"command"` + + // Script that will be run on click + Script string `json:"script"` + + // Children a list of children controls or containers contained within this + // container. + Children []*ControlDefinition `json:"children"` + + // Layout to use for laying out the contained children, either from top to + // bottom (`vertical`) or from left to right (`horizontal``). Defaults to a + // vertical layout. + Layout string `json:"layout"` +} + +// ControlDefinition describe a system control. +type ControlDefinition struct { + // Name of the control, will be displayed either on the button if it’s a + // control sending a command or as a label for controls which only display + // output. + Name string `json:"name"` + + // Command a single GCODE command to send to the printer. Will be rendered + // as a button which sends the command to the printer upon click. The button + // text will be the value of the `name` attribute. Mutually exclusive with + // `commands` and `script`. The rendered button be disabled if the printer + // is currently offline or printing or alternatively if the requirements + // defined via the `enabled` attribute are not met. + Command string `json:"command"` + + // Command a list of GCODE commands to send to the printer. Will be rendered + // as a button which sends the commands to the printer upon click. The + // button text will be the value of the `name` attribute. Mutually exclusive + // with `command` and `script`. The rendered button will be disabled if the + // printer is currently offline or printing or alternatively if the + // requirements defined via the `enabled` attribute are not met. + Commands []string `json:"commands"` + + // Script is the name of a full blown GCODE script to send to the printer. + // Will be rendered as a button which sends the script to the printer upon + // click. The button text will be the value of the name attribute. Mutually + // exclusive with `command` and `commands`. The rendered button will be + // disabled if the printer is currently offline or printing or alternatively + // if the requirements defined via the `enabled`` attribute are not met. + // + // Values of input parameters will be available in the template context + // under the `parameter` variable (e.g. an input parameter speed will be + // available in the script template as parameter.speed). On top of that all + // other variables defined in the GCODE template context will be available. + Script string `json:"script"` + + // JavaScript snippet to be executed when the button rendered for `command` + // or `commands` is clicked. This allows to override the direct sending of + // the command or commands to the printer with more sophisticated behaviour. + // The JavaScript snippet is `eval`’d and processed in a context where the + // control it is part of is provided as local variable `data` and the + // `ControlViewModel` is available as self. + JavasScript string `json:"javascript"` + + // Enabled a JavaScript snippet to be executed when the button rendered for + // `command` or `commands` is clicked. This allows to override the direct + // sending of the command or commands to the printer with more sophisticated + // behaviour. The JavaScript snippet is `eval`’d and processed in a context + // where the control it is part of is provided as local variable `data` and + // the `ControlViewModel` is available as `self`. + Enabled bool `json:"enabled"` + + // Input a list of definitions of input parameters for a command or + // commands, to be rendered as additional input fields. + Input *ControlInput `json:"input"` + + // Regex a regular expression to match against lines received from the + // printer to retrieve information from it (e.g. specific output). Together + // with template this allows rendition of received data from the printer + // within the UI. + Regex string `json:"regex"` + + // Template to use for rendering the match of `regex`. May contain + // placeholders in Python Format String Syntax[1] for either named groups + // within the regex (e.g. `Temperature: {temperature}` for a regex + // `T:\s*(?P\d+(\.\d*)`) or positional groups within the regex + // (e.g. `Position: X={0}, Y={1}, Z={2}, E={3}` for a regex + // `X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:([0-9.]+)`). + // https://docs.python.org/2/library/string.html#format-string-syntax + Template string `json:"template"` + + // Confirm a text to display to the user to confirm his button press. Can + // be used with sensitive custom controls like changing EEPROM values in + // order to prevent accidental clicks. + Confirm string `json:"confirm"` +} + +// ControlInput a list of definitions of input parameters for a command or +// commands, to be rendered as additional input fields. +type ControlInput struct { + // Name to display for the input field. + Name string `json:"name"` + + // Parameter name for the input field, used as a placeholder in + // command/commands. + Parameter string `json:"parameter"` + + // Default value for the input field. + Default interface{} `json:"default"` + + // Slider if defined instead of an input field a slider control will be + // rendered. + Slider struct { + // Minimum value of the slider, defaults to 0. + Min int `json:"min"` + + // Maximum value of the slider, defaults to 255. + Maximum int `json:"max"` + + // Step size per slider “tick”, defaults to 1. + Step int `json:"step"` + } `json:"slider"` +} + +// Settings are the current configuration of OctoPrint. +type SettingsResponse struct { + // API REST API settings. + API *APIConfig `json:"api"` + + // Features settings to enable or disable OctoPrint features. + Feature *FeaturesConfig `json:"feature"` + + //Folder settings to set custom paths for folders used by OctoPrint. + Folder *FolderConfig `json:"folder"` + + // Serial settings to configure the serial connection to the printer. + Serial *SerialConfig `json:"serial"` + + // Server settings to configure the server. + Server *ServerConfig `json:"server"` + + // Temperature profiles which will be displayed in the temperature tab. + Temperature *TemperatureConfig `json:"temperature"` + + // TerminalFilters to display in the terminal tab for filtering certain + // lines from the display terminal log. + TerminalFilters []*TerminalFilter `json:"terminalFilters"` + + // Webcam settings to configure webcam support. + Webcam *WebcamConfig `json:"json"` + + // Un-handled values + Appearance interface{} `json:"appearance"` + Plugins interface{} `json:"plugins"` + Printer interface{} `json:"printer"` +} + +// APIConfig REST API settings. +type APIConfig struct { + // Enabled whether to enable the API. + Enabled bool `json:"enabled"` + + // Key current API key needed for accessing the API + Key string `json:"key"` +} + +// FeaturesConfig settings to enable or disable OctoPrint features. +type FeaturesConfig struct { + // SizeThreshold maximum size a GCODE file may have to automatically be + // loaded into the viewer, defaults to 20MB. Maps to + // gcodeViewer.sizeThreshold in config.yaml. + SizeThreshold uint64 + + // MobileSizeThreshold maximum size a GCODE file may have on mobile devices + // to automatically be loaded into the viewer, defaults to 2MB. Maps to + // gcodeViewer.mobileSizeThreshold in config.yaml. + MobileSizeThreshold uint64 `json:"mobileSizeThreshold"` + + // TemperatureGraph whether to enable the temperature graph in the UI or not. + TemperatureGraph bool `json:"temperatureGraph"` + + // WaitForStart specifies whether OctoPrint should wait for the start + // response from the printer before trying to send commands during connect. + WaitForStart bool `json:"waitForStart"` + + // AlwaysSendChecksum specifies whether OctoPrint should send linenumber + + // checksum with every printer command. Needed for successful communication + // with Repetier firmware. + AlwaysSendChecksum bool `json:"alwaysSendChecksum"` + NeverSendChecksum bool `json:"neverSendChecksum"` + + // SDSupport specifies whether support for SD printing and file management + // should be enabled + SDSupport bool `json:"sdSupport"` + + // SDAlwaysAvailable whether to always assume that an SD card is present in + // the printer. Needed by some firmwares which don't report the SD card + // status properly. + SDAlwaysAvailable bool `json:"sdAlwaysAvailable"` + + // SDReleativePath Specifies whether firmware expects relative paths for + // selecting SD files. + SDRelativePath bool `json:"sdRelativePath"` + + // SwallowOkAfterResend whether to ignore the first ok after a resend + // response. Needed for successful communication with Repetier firmware. + SwallowOkAfterResend bool `json:"swallowOkAfterResend"` + + // RepetierTargetTemp whether the printer sends repetier style target + // temperatures in the format `TargetExtr0:` instead of + // attaching that information to the regular M105 responses. + RepetierTargetTemp bool `json:"repetierTargetTemp"` + + // ExternalHeatupDetection whether to enable external heatup detection (to + // detect heatup triggered e.g. through the printer's LCD panel or while + // printing from SD) or not. Causes issues with Repetier's "first ok then + // response" approach to communication, so disable for printers running + // Repetier firmware. + ExternalHeatupDetection bool `json:"externalHeatupDetection"` + + // KeyboardControl whether to enable the keyboard control feature in the + // control tab. + KeyboardControl bool `json:"keyboardControl"` + + // PollWatched whether to actively poll the watched folder (true) or to rely + // on the OS's file system notifications instead (false). + PollWatched bool `json:"pollWatched"` + + // IgnoreIdenticalResends whether to ignore identical resends from the + // printer (true, repetier) or not (false). + IgnoreIdenticalResends bool `json:"ignoreIdenticalResends"` + + // ModelSizeDetection whether to enable model size detection and warning + // (true) or not (false) + ModelSizeDetection bool `json:"modelSizeDetection"` + + // FirmwareDetection whether to attempt to auto detect the firmware of the + // printer and adjust settings accordingly (true) or not and rely on manual + // configuration (false) + FirmwareDetection bool `json:"firmwareDetection"` + + // PrintCancelConfirmation whether to show a confirmation on print + // cancelling (true) or not (false). + PrintCancelConfirmation bool `json:"printCancelConfirmation"` + + // BlockWhileDwelling whether to block all sending to the printer while a G4 + // (dwell) command is active (true, repetier) or not (false). + BlockWhileDwelling bool `json:"blockWhileDwelling"` +} + +// FolderConfig settings to set custom paths for folders used by OctoPrint. +type FolderConfig struct { + // Uploads absolute path where to store gcode uploads. Defaults to the + // uploads folder in the OctoPrint settings folder. + Uploads string `json:"uploads"` + + // Timelapse absolute path where to store finished timelapse recordings. + // Defaults to the timelapse folder in the OctoPrint settings dir. + Timelapse string `json:"timelapse"` + + // TimelapseTmp absolute path where to store temporary timelapse files. + // Defaults to the timelapse/tmp folder in the OctoPrint settings dir Maps + // to folder.timelapse_tmp in config.yaml. + TimelapseTmp string `json:"timelapseTmp"` + + // Logs absolute path where to store log files. Defaults to the logs folder + // in the OctoPrint settings dir + Logs string `json:"logs"` + + // Watched absolute path to a folder being watched for new files which then + // get automatically added to OctoPrint (and deleted from that folder). + // Can e.g. be used to define a folder which can then be mounted from remote + // machines and used as local folder for quickly adding downloaded and/or + // sliced objects to print in the future. + Watched string `json:"watched"` +} + +// SerialConfig settings to configure the serial connection to the printer. +type SerialConfig struct { + // Port is the default serial port, defaults to unset (= AUTO) + Port string `json:"port"` + + // Baudrate is the default baudrate, defaults to unset (= AUTO) + Baudrate int `json:"baudrate"` + + // Available serial ports + PortOptions []string `json:"portOptions"` + + // Available serial baudrates + BaudrateOptions []int `json:"baudrateOptions"` + + // Autoconnect whether to automatically connect to the printer on server + // startup (if available). + Autoconnect bool `json:"autoconnect"` + + // TimeoutConnection for waiting to establish a connection with the selected + // port, in seconds. Defaults to 2 sec. Maps to serial.timeout.connection in + // config.yaml + TimeoutConnection float64 `json:"timeoutConnection"` + + // TimeoutDetection for waiting for a response from the currently tested + // port during autodetect, in seconds. Defaults to 0.5 sec Maps to + // serial.timeout.detection in config.yaml + TimeoutDetection float64 `json:"timeoutDetection"` + + // TimeoutCommunication during serial communication, in seconds. Defaults to + // 30 sec. Maps to serial.timeout.communication in config.yaml + TimeoutCommunication float64 `json:"timeoutCommunication"` + + // TimeoutTemperature after which to query temperature when no target is + // set. Maps to serial.timeout.temperature in config.yaml + TimeoutTemperature float64 `json:"timeoutTemperature"` + + // TimeoutTemperatureTargetSet after which to query temperature when a + // target is set. Maps to serial.timeout.temperatureTargetSet in config.yaml + TimeoutTemperatureTargetSet float64 `json:"timeoutTemperatureTargetSet"` + + // TimeoutSDStatus after which to query the SD status while SD printing. + // Maps to serial.timeout.sdStatus in config.yaml + TimeoutSDStatus float64 `json:"timeoutSdStatus"` + + // Log whether to log whole communication to serial.log (warning: might + // decrease performance) + Log bool `json:"log"` + + // AdditionalPorts use this to define additional patterns to consider for + // serial port listing. Must be a valid "glob" pattern (see + // http://docs.python.org/2/library/glob.html). Defaults to not set. + AdditionalPorts []string `json:"additionalPorts"` + + // AdditionalBaudrates use this to define additional baud rates to offer for + // connecting to serial ports. Must be a valid integer. Defaults to not set + AdditionalBaudrates []int `json:"additionalBaudrates"` + + // LongRunningCommands which are known to take a long time to be + // acknowledged by the firmware. E.g. homing, dwelling, auto leveling etc. + LongRunningCommands []string `json:"longRunningCommands"` + + // ChecksumRequiringCommands which need to always be send with a checksum. + // Defaults to only M110 + ChecksumRequiringCommands []string `json:"checksumRequiringCommands"` + + // HelloCommand to send in order to initiate a handshake with the printer. + // Defaults to "M110 N0" which simply resets the line numbers in the + // firmware and which should be acknowledged with a simple "ok". + HelloCommand string `json:"helloCommand"` + + // IgnoreErrorsFromFirmware whether to completely ignore errors from the + // firmware or not + IgnoreErrorsFromFirmware bool `json:"ignoreErrorsFromFirmware"` + + // DisconnectOnErrors whether to disconnect on errors or not. + DisconnectOnErrors bool `json:"disconnectOnErrors"` + + // TriggerOkForM29 whether to "manually" trigger an ok for M29 (a lot of + // versions of this command are buggy and the responds skips on the ok) + TriggerOkForM29 bool `json:"triggerOkForM29"` + + // SupportResendsWIthoutOk whether to support resends without follow-up ok + // or not. + SupportResendsWIthoutOk string `json:"supportResendsWIthoutOk"` + + // Maps to serial.maxCommunicationTimeouts.idle in config.yaml + MaxTimeoutsIdle float64 `json:"maxTimeoutsIdle"` + + // MaxTimeoutsPrinting maximum number of consecutive communication timeouts + // after which the printer will be considered dead and OctoPrint disconnects + // with an error. Maps to serial.maxCommunicationTimeouts.printing in + // config.yaml + MaxTimeoutsPrinting float64 `json:"maxTimeoutsPrinting"` + + // MaxTimeoutsPrinting maximum number of consecutive communication timeouts + // after which the printer will be considered dead and OctoPrint disconnects + // with an error. Maps to serial.maxCommunicationTimeouts.log in config.yaml + MaxTimeoutsLong float64 `json:"maxTimeoutsLong"` +} + +// ServerConfig settings to configure the server. +type ServerConfig struct { + // Commands to restart/shutdown octoprint or the system it's running on. + Commands struct { + // ServerRestartCommand to restart OctoPrint, defaults to being unset + ServerRestartCommand string `json:"serverRestartCommand"` + + //SystemRestartCommand to restart the system OctoPrint is running on, + // defaults to being unset + SystemRestartCommand string `json:"systemRestartCommand"` + + // SystemShutdownCommand Command to shut down the system OctoPrint is + // running on, defaults to being unset + SystemShutdownCommand string `json:"systemShutdownCommand"` + } `json:"commands"` + + // Diskspace settings of when to display what disk space warning + Diskspace struct { + // Warning threshold (bytes) after which to consider disk space becoming + // sparse, defaults to 500MB. + Warning uint64 `json:"warning"` + + // Critical threshold (bytes) after which to consider disk space becoming + // critical, defaults to 200MB. + Critical uint64 `json:"critical"` + } `json:"diskspace"` + // OnlineCheck configuration of the regular online connectivity check. + OnlineCheck struct { + // Enabled whether the online check is enabled, defaults to false due to + // valid privacy concerns. + Enabled bool `json:"enabled"` + + // Interval in which to check for online connectivity (in seconds) + Interval int `json:"interval"` + + // Host DNS host against which to check (default: 8.8.8.8 aka Google's DNS) + Host string `json:"host"` + + // DNS port against which to check (default: 53 - the default DNS port) + Port int `json:"port"` + } `json:"onlineCheck"` + // PluginBlacklist configuration of the plugin blacklist + PluginBlacklist struct { + // Enabled whether use of the blacklist is enabled, defaults to false + Enabled bool `json:"enabled"` + + // URL from which to fetch the blacklist + URL string `json:"url"` + + // TTL is time to live of the cached blacklist, in secs (default: 15mins) + TTL int `json:"ttl"` + } `json:"pluginBlacklist"` +} + +// TemperatureConfig temperature profiles which will be displayed in the +// temperature tab. +type TemperatureConfig struct { + // Graph cutoff in minutes. + Cutoff int `json:"cutoff"` + + // Profiles which will be displayed in the temperature tab. + TemperaturePresets []*TemperaturePreset `json:"profiles"` + + // SendAutomatically enable this to have temperature fine adjustments you + // do via the + or - button be sent to the printer automatically. + SendAutomatically bool `json:"sendAutomatically"` + + // SendAutomaticallyAfter OctoPrint will use this delay to limit the number + // of sent temperature commands should you perform multiple fine adjustments + // in a short time. + SendAutomaticallyAfter float64 `json:"sendAutomaticallyAfter"` +} + +// TerminalFilter to display in the terminal tab for filtering certain lines +// from the display terminal log. +type TerminalFilter struct { + Name string `json:"name"` + RegEx string `json:"regex"` +} + +// WebcamConfig settings to configure webcam support. +type WebcamConfig struct { + // StreamUrl use this option to enable display of a webcam stream in the + // UI, e.g. via MJPG-Streamer. Webcam support will be disabled if not + // set. Maps to webcam.stream in config.yaml. + StreamURL string `json:"streamUrl"` + + // SnapshotURL use this option to enable timelapse support via snapshot, + // e.g. via MJPG-Streamer. Timelapse support will be disabled if not set. + // Maps to webcam.snapshot in config.yaml. + SnapshotURL string `json:"snapshotUrl"` + + // FFmpegPath path to ffmpeg binary to use for creating timelapse + // recordings. Timelapse support will be disabled if not set. Maps to + // webcam.ffmpeg in config.yaml. + FFmpegPath string `json:"ffmpegPath"` + + // Bitrate to use for rendering the timelapse video. This gets directly + // passed to ffmpeg. + Bitrate int `json:"bitrate"` + + // FFmpegThreads number of how many threads to instruct ffmpeg to use for + // encoding. Defaults to 1. Should be left at 1 for RPi1. + FFmpegThreads int `json:"ffmpegThreads"` + + // Watermark whether to include a "created with OctoPrint" watermark in the + // generated timelapse movies. + Watermark string `json:"watermark"` + + // FlipH whether to flip the webcam horizontally. + FlipH bool `json:"flipH"` + + // FlipV whether to flip the webcam vertically. + FlipV bool `json:"flipV"` + + // Rotate90 whether to rotate the webcam 90° counter clockwise. + Rotate90 bool `json:"rotate90"` +} + + + + +// TemperaturePreset describes the temperature preset for a given material. +type TemperaturePreset struct { + Name string `json:"name"` + Bed float64 `json:"bed"` + Extruder float64 `json:"extruder"` +} + + + + +type PrinterProfilesResponse struct { + Profiles []*PrinterProfile `json:"profiles"` +} + +type PrinterProfile struct { + Id string `json:"id"` + Name string `json:"name"` + + Volume struct { + FormFactor string `json:"formFactor"` + Origin string `json:"origin"` + Width float64 `json:"width"` + Depth float64 `json:"depth"` + Height float64 `json:"height"` + } `json:"volume"` + + Extruder struct { + Count int `json:"count"` + SharedNozzle bool `json:"sharedNozzle"` + } `json:"extruder"` +} diff --git a/octoprintApis/common_test.go b/octoprintApis/common_test.go new file mode 100644 index 00000000..28c4151c --- /dev/null +++ b/octoprintApis/common_test.go @@ -0,0 +1,176 @@ +package octoprintApis + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHistoricTemperatureData(t *testing.T) { + js := []byte(`{ + "time": 1395651928, + "tool0": { + "actual": 214.8821, + "target": 220.0 + }, + "tool1": { + "actual": 25.3, + "target": null + } + }`) + + h := &HistoricTemperatureData{} + + err := json.Unmarshal(js, h) + assert.NoError(t, err) + + assert.Len(t, h.Tools, 2) + assert.False(t, h.Time.IsZero()) + assert.Equal(t, h.Tools["tool0"].Target, 220.) + assert.Equal(t, h.Tools["tool1"].Actual, 25.3) +} + +func TestTemperatureState(t *testing.T) { + js := []byte(`{ + "tool0": { + "actual": 214.8821, + "target": 220.0, + "offset": 0 + }, + "tool1": { + "actual": 25.3, + "target": null, + "offset": 0 + }, + "history": [ + { + "time": 1395651928, + "tool0": { + "actual": 214.8821, + "target": 220.0 + }, + "tool1": { + "actual": 25.3, + "target": null + } + }, + { + "time": 1395651926, + "tool0": { + "actual": 212.32, + "target": 220.0 + }, + "tool1": { + "actual": 25.1 + } + } + ] + }`) + + r := &TemperatureState{} + + err := json.Unmarshal(js, r) + assert.NoError(t, err) + + assert.Len(t, r.Current, 2) + assert.Equal(t, r.Current["tool0"].Actual, 214.8821) + assert.Equal(t, r.Current["tool1"].Actual, 25.3) + + assert.Len(t, r.History, 2) + assert.Equal(t, r.History[0].Tools["tool0"].Actual, 214.8821) + assert.Equal(t, r.History[1].Tools["tool0"].Actual, 212.32) +} + +func TestFullStateResponse(t *testing.T) { + js := []byte(` + { + "temperature":{ + "tool0":{ + "actual":214.8821, + "target":220.0, + "offset":0 + }, + "tool1":{ + "actual":25.3, + "target":null, + "offset":0 + }, + "bed":{ + "actual":50.221, + "target":70.0, + "offset":5 + }, + "history":[{ + "time":1395651928, + "tool0":{ + "actual":214.8821, + "target":220.0 + }, + "tool1":{ + "actual":25.3, + "target":null + }, + "bed":{ + "actual":50.221, + "target":70.0 + } + },{ + "time":1395651926, + "tool0":{ + "actual":212.32, + "target":220.0 + }, + "tool1":{ + "actual":25.1, + "target":null + }, + "bed":{ + "actual":49.1123, + "target":70.0 + } + }] + }, + "sd":{ + "ready":true + }, + "state":{ + "text":"Operational", + "flags":{ + "operational":true, + "paused":false, + "printing":false, + "sdReady":true, + "error":false, + "ready":true, + "closedOrError":false + } + } + } + `) + + r := &FullStateResponse{} + + err := json.Unmarshal(js, r) + assert.NoError(t, err) + + assert.Equal(t, r.State.Text, "Operational") + assert.True(t, r.State.Flags.Ready) + assert.True(t, r.SD.Ready) + assert.Len(t, r.Temperature.Current, 3) + assert.Len(t, r.Temperature.History, 2) +} + +func TestFileInformation_IsFolder(t *testing.T) { + f := &FileInformation{TypePath: []string{"folder"}} + assert.True(t, f.IsFolder()) + + f = &FileInformation{} + assert.False(t, f.IsFolder()) +} + +func TestJSONTime_UnmarshalJSONWithNull(t *testing.T) { + time := &JSONTime{} + err := time.UnmarshalJSON([]byte("null")) + assert.NoError(t, err) +} diff --git a/octoprintApis/connection.go b/octoprintApis/connection.go new file mode 100755 index 00000000..c85a4ccf --- /dev/null +++ b/octoprintApis/connection.go @@ -0,0 +1,112 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "io" +) + +const URIConnection = "/api/connection" + +var ConnectionErrors = StatusMapping{ + 400: "The selected port or baudrate for a connect command are not part of the available option", +} + +// ConnectionRequest Retrieve the current connection settings, including +// information regarding the available baudrates and serial ports and the +// current connection state. +type ConnectionRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *ConnectionRequest) Do(c *Client) (*ConnectionResponse, error) { + b, err := c.doJSONRequest("GET", URIConnection, nil, nil) + if err != nil { + return nil, err + } + + r := &ConnectionResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} + +// ConnectRequest sets the given target temperature on the printer’s tools. +type ConnectRequest struct { + // Port specific port to connect to. If not set the current `portPreference` + // will be used, or if no preference is available auto detection will be + // attempted. + Port string `json:"port,omitempty"` + // BaudRate specific baudrate to connect with. If not set the current + // `baudratePreference` will be used, or if no preference is available auto + // detection will be attempted. + BaudRate int `json:"baudrate,omitempty"` + // PrinterProfile specific printer profile to use for connection. If not set + // the current default printer profile will be used. + PrinterProfile string `json:"printerProfile,omitempty"` + // Save whether to save the request’s port and baudrate settings as new + // preferences. + Save bool `json:"save"` + // Autoconnect whether to automatically connect to the printer on + // OctoPrint’s startup in the future. + Autoconnect bool `json:"autoconnect"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ConnectRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) + return err +} + +func (cmd *ConnectRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ConnectRequest + }{ + Command: "connect", + ConnectRequest: *cmd, + }) +} + +// DisconnectRequest instructs OctoPrint to disconnect from the printer. +type DisconnectRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *DisconnectRequest) Do(c *Client) error { + payload := map[string]string{"command": "disconnect"} + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(payload); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) + return err +} + +// FakesACKRequest fakes an acknowledgment message for OctoPrint in case one got +// lost on the serial line and the communication with the printer since stalled. +// +// This should only be used in “emergencies” (e.g. to save prints), the reason +// for the lost acknowledgment should always be properly investigated and +// removed instead of depending on this “symptom solver”. +type FakesACKRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *FakesACKRequest) Do(c *Client) error { + payload := map[string]string{"command": "fake_ack"} + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(payload); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) + return err +} diff --git a/octoprintApis/files.go b/octoprintApis/files.go new file mode 100755 index 00000000..2f461fb0 --- /dev/null +++ b/octoprintApis/files.go @@ -0,0 +1,250 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "mime/multipart" +) + +type Location string + +const ( + // URIFiles = "/api/files" + + Local Location = "local" + SDCard Location = "sdcard" +) + +var ( + FilesLocationGETErrors = StatusMapping{ + 404: "Location is neither local nor sdcard", + } + FilesLocationPOSTErrors = StatusMapping{ + 400: "No file or foldername are included in the request, userdata was provided but could not be parsed as JSON or the request is otherwise invalid.", + 404: "Location is neither local nor sdcard or trying to upload to SD card and SD card support is disabled", + 409: "The upload of the file would override the file that is currently being printed or if an upload to SD card was requested and the printer is either not operational or currently busy with a print job.", + 415: "The file is neither a gcode nor an stl file (or it is an stl file but slicing support is disabled)", + 500: "The upload failed internally", + } + FilesLocationPathPOSTErrors = StatusMapping{ + 400: "The command is unknown or the request is otherwise invalid", + 415: "A slice command was issued against something other than an STL file.", + 404: "Location is neither local nor sdcard or the requested file was not found", + 409: "Selected file is supposed to start printing directly but the printer is not operational or if a file to be sliced is supposed to be selected or start printing directly but the printer is not operational or already printing.", + } + FilesLocationDeleteErrors = StatusMapping{ + 404: "Location is neither local nor sdcard", + 409: "The file to be deleted is currently being printed", + } +) + +// FileRequest is now in FileRequest.go +// TODO: remove this commented code +// FileRequest retrieves the selected file’s or folder’s information. +// type FileRequest struct { +// // Location of the file for which to retrieve the information, either +// // `local` or `sdcard`. +// Location Location + +// // Filename of the file for which to retrieve the information +// Filename string + +// // Recursive if set to true, return all files and folders recursively. +// // Otherwise only return items on same level. +// Recursive bool +// } + +// // Do sends an API request and returns the API response +// func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { +// uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, +// cmd.Location, cmd.Filename, cmd.Recursive, +// ) + +// b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) +// if err != nil { +// return nil, err +// } + +// r := &FileInformation{} +// if err := json.Unmarshal(b, r); err != nil { +// return nil, err +// } + +// return r, err +// } + + + + + +// FilesRequest retrieve information regarding all files currently available and +// regarding the disk space still available locally in the system. +type FilesRequest struct { + // Location is the target location . + Location Location + // Recursive if set to true, return all files and folders recursively. + // Otherwise only return items on same level. + Recursive bool +} + +// Do sends an API request and returns the API response. +func (cmd *FilesRequest) Do(c *Client) (*FilesResponse, error) { + uri := fmt.Sprintf("%s?recursive=%t", URIFiles, cmd.Recursive) + if cmd.Location != "" { + uri = fmt.Sprintf("%s/%s?recursive=%t", URIFiles, cmd.Location, cmd.Recursive) + } + + b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) + if err != nil { + return nil, err + } + + r := &FilesResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + if len(r.Children) > 0 { + r.Files = r.Children + } + + return r, err +} + +// UploadFileRequest uploads a file to the selected location or create a new +// empty folder on it. +type UploadFileRequest struct { + // Location is the target location to which to upload the file. Currently + // only `local` and `sdcard` are supported here, with local referring to + // OctoPrint’s `uploads` folder and `sdcard` referring to the printer’s + // SD card. If an upload targets the SD card, it will also be stored + // locally first. + Location Location + // Select whether to select the file directly after upload (true) or not + // (false). Optional, defaults to false. Ignored when creating a folder. + Select bool + //Print whether to start printing the file directly after upload (true) or + // not (false). If set, select is implicitely true as well. Optional, + // defaults to false. Ignored when creating a folder. + Print bool + b *bytes.Buffer + w *multipart.Writer +} + +// AddFile adds a new file to be uploaded from a given reader. +func (req *UploadFileRequest) AddFile(filename string, r io.Reader) error { + w, err := req.writer().CreateFormFile("file", filename) + if err != nil { + return err + } + + _, err = io.Copy(w, r) + return err + +} + +func (req *UploadFileRequest) writer() *multipart.Writer { + if req.w == nil { + req.b = bytes.NewBuffer(nil) + req.w = multipart.NewWriter(req.b) + } + + return req.w +} + +// AddFolder adds a new folder to be created. +func (req *UploadFileRequest) AddFolder(folder string) error { + return req.writer().WriteField("foldername", folder) +} + +// Do sends an API request and returns the API response. +func (req *UploadFileRequest) Do(c *Client) (*UploadFileResponse, error) { + req.addSelectPrintAndClose() + + uri := fmt.Sprintf("%s/%s", URIFiles, req.Location) + b, err := c.doRequest("POST", uri, req.w.FormDataContentType(), req.b, FilesLocationPOSTErrors) + if err != nil { + return nil, err + } + + r := &UploadFileResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} + +func (req *UploadFileRequest) addSelectPrintAndClose() error { + err := req.writer().WriteField("select", fmt.Sprintf("%t", req.Select)) + if err != nil { + return err + } + + err = req.writer().WriteField("print", fmt.Sprintf("%t", req.Print)) + if err != nil { + return err + } + + return req.writer().Close() +} + +// DeleteFileRequest delete the selected path on the selected location. +type DeleteFileRequest struct { + // Location is the target location on which to delete the file, either + // `local` (for OctoPrint’s uploads folder) or \sdcard\ for the printer’s + // SD card (if available) + Location Location + // Path of the file to delete + Path string +} + +// Do sends an API request and returns error if any. +func (req *DeleteFileRequest) Do(c *Client) error { + uri := fmt.Sprintf("%s/%s/%s", URIFiles, req.Location, req.Path) + if _, err := c.doJSONRequest("DELETE", uri, nil, FilesLocationDeleteErrors); err != nil { + return err + } + + return nil +} + +// SelectFileRequest is now in SelectFileRequest.go +// // SelectFileRequest selects a file for printing. +// type SelectFileRequest struct { +// // Location is target location on which to send the command for is located, +// // either local (for OctoPrint’s uploads folder) or sdcard for the +// // printer’s SD card (if available) +// Location Location `json:"-"` +// // Path of the file for which to issue the command +// Path string `json:"-"` +// // Print, if set to true the file will start printing directly after +// // selection. If the printer is not operational when this parameter is +// // present and set to true, the request will fail with a response of +// // 409 Conflict. +// Print bool `json:"print"` +// } + +// // Do sends an API request and returns an error if any. +// func (cmd *SelectFileRequest) Do(c *Client) error { +// b := bytes.NewBuffer(nil) +// if err := cmd.encode(b); err != nil { +// return err +// } + +// uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) +// _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) +// return err +// } + +// func (cmd *SelectFileRequest) encode(w io.Writer) error { +// return json.NewEncoder(w).Encode(struct { +// Command string `json:"command"` +// SelectFileRequest +// }{ +// Command: "select", +// SelectFileRequest: *cmd, +// }) +// } diff --git a/octoprintApis/files_test.go b/octoprintApis/files_test.go new file mode 100644 index 00000000..72b37ad8 --- /dev/null +++ b/octoprintApis/files_test.go @@ -0,0 +1,86 @@ +package octoprintApis + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUploadFileRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &UploadFileRequest{Location: Local} + err := r.AddFile("foo.gcode", bytes.NewBufferString("foo")) + assert.NoError(t, err) + + state, err := r.Do(cli) + assert.NoError(t, err) + assert.Equal(t, "foo.gcode", state.File.Local.Name) + + err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) + assert.NoError(t, err) +} + +func TestUploadFileRequest_DoWithFolder(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &UploadFileRequest{Location: Local} + err := r.AddFolder("qux") + assert.NoError(t, err) + + state, err := r.Do(cli) + assert.NoError(t, err) + assert.Equal(t, true, state.Done) +} + +func TestFilesRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + ur := &UploadFileRequest{Location: Local} + err := ur.AddFile("foo.gcode", bytes.NewBufferString("foo")) + assert.NoError(t, err) + + _, err = ur.Do(cli) + assert.NoError(t, err) + + files, err := (&FilesRequest{}).Do(cli) + assert.NoError(t, err) + + assert.True(t, len(files.Files) >= 1) + err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) + assert.NoError(t, err) + return + + r := &FileRequest{Location: Local, Filename: "foo.gcode"} + file, err := r.Do(cli) + assert.NoError(t, err) + + assert.Equal(t, "foo.gcode", file.Name) + + err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) + assert.NoError(t, err) +} + +func TestSelectFileRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + ur := &UploadFileRequest{Location: Local} + err := ur.AddFile("foo2.gcode", bytes.NewBufferString("foo")) + assert.NoError(t, err) + _, err = ur.Do(cli) + assert.NoError(t, err) + + r := &SelectFileRequest{Location: Local, Path: "foo2.gcode"} + err = r.Do(cli) + assert.NoError(t, err) +} + +func xxxTestFilesRequest_DoWithLocation(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + files, err := (&FilesRequest{Location: SDCard}).Do(cli) + assert.NoError(t, err) + + assert.Len(t, files.Files, 0) +} diff --git a/octoprintApis/job.go b/octoprintApis/job.go new file mode 100755 index 00000000..6c6b69cc --- /dev/null +++ b/octoprintApis/job.go @@ -0,0 +1,175 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "io" + "log" +) + + +var JobToolErrors = StatusMapping{ + 409: "Printer is not operational or the current print job state does not match the preconditions for the command.", +} + + + + +// JobRequest is now in JobRequest.go +// // JobRequest retrieve information about the current job (if there is one). +// type JobRequest struct{} + +// // Do sends an API request and returns the API response. +// func (cmd *JobRequest) Do(c *Client) (*JobResponse, error) { +// bytes, err := c.doJSONRequest("GET", JobTool, nil, nil) +// if err != nil { +// return nil, err +// } + +// response := &JobResponse{} +// if err := json.Unmarshal(bytes, response); err != nil { +// return nil, err +// } + +// return response, err +// } + + + + + +// StartRequest starts the print of the currently selected file. +type StartRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *StartRequest) Do(c *Client) error { + payload := map[string]string{"command": "start"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) + return err +} + +// CancelRequest cancels the current print job. +type CancelRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *CancelRequest) Do(c *Client) error { + payload := map[string]string{"command": "cancel"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) + return err +} + +// RestartRequest restart the print of the currently selected file from the +// beginning. There must be an active print job for this to work and the print +// job must currently be paused +type RestartRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *RestartRequest) Do(c *Client) error { + payload := map[string]string{"command": "restart"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) + return err +} + +type PauseAction string + +const ( + // Pause the current job if it’s printing, does nothing if it’s already paused. + Pause PauseAction = "pause" + + // Resume the current job if it’s paused, does nothing if it’s printing. + Resume PauseAction = "resume" + + // Toggle the pause state of the job, pausing it if it’s printing and + // resuming it if it’s currently paused. + Toggle PauseAction = "toggle" +) + +// PauseRequest pauses/resumes/toggles the current print job. +type PauseRequest struct { + // Action specifies which action to take. + // In order to stay backwards compatible to earlier iterations of this API, + // the default action to take if no action parameter is supplied is to + // toggle the print job status. + Action PauseAction `json:"action"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PauseRequest) Do(c *Client) error { + buffer := bytes.NewBuffer(nil) + if err := cmd.encode(buffer); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) + return err +} + + + + + + +// Do sends an API request and returns an error if any. +func (cmd *PauseRequest) DoWithLogging(c *Client) error { + log.Println("job.Do() - starting call") + + buffer := bytes.NewBuffer(nil) + err := cmd.encode(buffer) + if err != nil { + log.Println("job.Do() - encode() failed") + return err + } + + // str := string([]byte(buffer.Bytes)) + str := string(buffer.Bytes()) + log.Printf("job.Do() - bytes are: '%s' abc", str) + + + log.Println("job.Do() - about to call POST") + body, err2 := c.doJSONRequestWithLogging("POST", JobTool, buffer, JobToolErrors) + + log.Println("job.Do() - finished calling POST") + if err2 != nil { + log.Println("job.Do() - call to doJSONRequest() failed") + log.Printf("job.Do() - err2 is: %s", err2.Error()) + } + + if err2 == nil { + log.Println("job.Do() - call to doJSONRequest() passed") + str = string(body) + log.Printf("job.Do() - body is: %s", str) + } + + return err +} + + + + +func (cmd *PauseRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PauseRequest + }{ + Command: "pause", + PauseRequest: *cmd, + }) +} diff --git a/octoprintApis/plugin_manager.go b/octoprintApis/plugin_manager.go new file mode 100755 index 00000000..375ad8c5 --- /dev/null +++ b/octoprintApis/plugin_manager.go @@ -0,0 +1,76 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "log" +) + +const pluginManagerRequestURI = "/api/plugin/pluginmanager" + + +// Plugin - +type Plugin struct { + Author string `json:"author"` + Blacklisted bool `json:"blacklisted"` + Bundled bool `json:"bundled"` + Description string `json:"description"` + // DisablingDiscouraged bool `json:"disabling_discouraged"` + Enabled bool `json:"enabled"` + ForcedDisabled bool `json:"forced_disabled"` + Incompatible bool `json:"incompatible"` + Key string `json:"key"` + License string `json:"license"` + Managable bool `json:"managable"` + Name string `json:"name"` + // notifications: [] + Origin string `json:"origin"` + PendingDisable bool `json:"pending_disable"` + PendingEnable bool `json:"pending_enable"` + PendingInstall bool `json:"pending_install"` + PendingUninstall bool `json:"pending_uninstall"` + Python string `json:"python"` + SafeModeVictim bool `json:"safe_mode_victim"` + URL string `json:"url"` + Version string `json:"version"` +} + +// GetPluginManagerInfoRequest - +type GetPluginManagerInfoRequest struct { + Command string `json:"command"` +} + +// GetPluginManagerInfoResponse - +type GetPluginManagerInfoResponse struct { + Octoprint string `json:"octoprint"` + Online bool `json:"online"` + //orphan_data: { } + OS string `json:"os"` + //pip: {} + Plugins []Plugin `json:"plugins"` +} + +// Do - +func (cmd *GetPluginManagerInfoRequest) Do(c *Client) (*GetPluginManagerInfoResponse, error) { + cmd.Command = "get_settings" + + params := bytes.NewBuffer(nil) + if err := json.NewEncoder(params).Encode(cmd); err != nil { + log.Println("plugin_manager.Do() - Encode() failed") + return nil, err + } + + b, err := c.doJSONRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) + if err != nil { + log.Println("plugin_manager.Do() - doJSONRequest() failed") + return nil, err + } + + r := &GetPluginManagerInfoResponse{} + if err := json.Unmarshal(b, r); err != nil { + log.Println("plugin_manager.Do() - Unmarshal() failed") + return nil, err + } + + return r, err +} diff --git a/octoprintApis/printer.go b/octoprintApis/printer.go new file mode 100755 index 00000000..77657313 --- /dev/null +++ b/octoprintApis/printer.go @@ -0,0 +1,670 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" + // "strings" +) + +const ( + // URIPrinter = "/api/printer" + URIPrintHead = "/api/printer/printhead" + URIPrintTool = "/api/printer/tool" + URIPrintBed = "/api/printer/bed" + URIPrintSD = "/api/printer/sd" + URICommand = "/api/printer/command" + URICommandCustom = "/api/printer/command/custom" +) + +var ( + PrintErrors = StatusMapping{ + 409: "Printer is not operational", + } + PrintHeadJobErrors = StatusMapping{ + 400: "Invalid axis specified, invalid value for travel amount for a jog command or factor for feed rate or otherwise invalid request", + 409: "Printer is not operational or currently printing", + } + PrintToolErrors = StatusMapping{ + 400: "Targets or offsets contains a property or tool contains a value not matching the format tool{n}, the target/offset temperature, extrusion amount or flow rate factor is not a valid number or outside of the supported range, or if the request is otherwise invalid", + 409: "Printer is not operational", + } + PrintBedErrors = StatusMapping{ + 409: "Printer is not operational or the selected printer profile does not have a heated bed.", + } + PrintSDErrors = StatusMapping{ + 404: "SD support has been disabled in OctoPrint’s settings.", + 409: "SD card has not been initialized.", + } +) + + + + + +// FullStateRequest has been moved to FullStateRequest.go +// // FullStateRequest retrieves the current state of the printer. +// type FullStateRequest struct { +// // bytes if true retrieve the temperature history. +// IncludeHistory bool + +// // Limit limits the amount of returned history data points. +// Limit int + +// // Exclude list of fields to exclude from the response (e.g. if not +// // needed by the client). Valid values to supply here are `temperature`, +// // `sd` and `state`. +// Exclude []string +// } + +// // FullStateResponse contains informantion about the current state of the printer. +// type FullStateResponse struct { +// // TemperatureStateResponse is the printer’s temperature state data. +// Temperature TemperatureStateResponse `json:"temperature"` + +// // SD is the printer’s sd state data. +// SD SDState `json:"sd"` + +// // State is the printer’s general state. +// State PrinterState `json:"state"` +// } + +// // Do sends an API request and returns the API response. +// func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { +// uri := fmt.Sprintf( +// "%s?history=%t&limit=%d&exclude=%s", +// URIPrinter, +// cmd.IncludeHistory, +// cmd.Limit, +// strings.Join(cmd.Exclude, ","), +// ) + +// log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) +// //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state +// /* +// { +// "temperature": { +// "bed": { +// "actual": 26.9, +// "offset": 0, +// "target": 0.0 +// }, +// "history": [ +// { +// "bed": { +// "actual": 26.9, +// "target": 0.0 +// }, +// "time": 1598235178, +// "tool0": { +// "actual": 35.4, +// "target": 0.0 +// } +// } +// ], +// "tool0": { +// "actual": 35.4, +// "offset": 0, +// "target": 0.0 +// } +// } +// } +// */ + + +// bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) +// if err != nil { +// return nil, err +// } + +// response := &FullStateResponse{} +// if err := json.Unmarshal(bytes, response); err != nil { +// return nil, err +// } + +// return response, err +// } + + + + + + +// FullStateRequest retrieves the current state of the printer. +type TemperatureDataRequest struct { + // bytes if true retrieve the temperature history. + // IncludeHistory bool + + // Limit limits the amount of returned history data points. + // Limit int + + // Exclude list of fields to exclude from the response (e.g. if not + // needed by the client). Valid values to supply here are `temperature`, + // `sd` and `state`. + // Exclude []string +} + +// FullStateResponse contains informantion about the current state of the printer. +type TemperatureDataResponse struct { + // TemperatureStateResponse is the printer’s temperature state data. + TemperatureStateResponse TemperatureStateResponse `json:"temperature"` + + // SD is the printer’s sd state data. + // SD SDState `json:"sd"` + + // State is the printer’s general state. + // State PrinterState `json:"state"` +} + +// Do sends an API request and returns the API response. +func (cmd *TemperatureDataRequest) Do(c *Client) (*TemperatureDataResponse, error) { + uri := fmt.Sprintf( + "%s?history=false&exclude=sd,state", + URIPrinter, + ) + + log.Printf("TODO-Remove: StateRequest (TemperatureDataResponse) uri is: %s", uri) + //StateRequest uri is: %s /api/printer?history=false&exclude=sd,state + /* + { + "temperature": { + "bed": { + "actual": 26.9, + "offset": 0, + "target": 0.0 + }, + "tool0": { + "actual": 35.4, + "offset": 0, + "target": 0.0 + } + } + } + */ + + + bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) + if err != nil { + return nil, err + } + + response := &TemperatureDataResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} + + + + + + + + + + + + + + + + + + + +// PrintHeadJogRequest jogs the print head (relatively) by a defined amount in +// one or more axes. +type PrintHeadJogRequest struct { + // X is the amount distance to travel in mm or coordinate to jog print head + // on x axis. + X float64 `json:"x,omitempty"` + // Y is the amount distance to travel in mm or coordinate to jog print head + // on y axis. + Y float64 `json:"y,omitempty"` + // Z is the amount distance to travel in mm.or coordinate to jog print head + // on x axis. + Z float64 `json:"z,omitempty"` + // Absolute is whether to move relative to current position (provided axes + // values are relative amounts) or to absolute position (provided axes + // values are coordinates) + Absolute bool `json:"absolute"` + // Speed at which to move in mm/s. If not provided, minimum speed for all + // selected axes from printer profile will be used. + Speed int `json:"speed,omitempty"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PrintHeadJogRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintHead, b, PrintHeadJobErrors) + + return err +} + +func (cmd *PrintHeadJogRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PrintHeadJogRequest + }{ + Command: "jog", + PrintHeadJogRequest: *cmd, + }) +} + +// PrintHeadHomeRequest homes the print head in all of the given axes. +type PrintHeadHomeRequest struct { + // Axes is a list of axes which to home. + Axes []Axis `json:"axes"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PrintHeadHomeRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintHead, b, PrintHeadJobErrors) + return err +} + +func (cmd *PrintHeadHomeRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PrintHeadHomeRequest + }{ + Command: "home", + PrintHeadHomeRequest: *cmd, + }) +} + +// ToolStateRequest retrieves the current temperature data (actual, target and +// offset) plus optionally a (limited) history (actual, target, timestamp) for +// all of the printer’s available tools. +type ToolStateRequest struct { + // History if true retrieve the temperature history. + IncludeHistory bool + + // Limit limtis amount of returned history data points. + Limit int +} + +// Do sends an API request and returns the API response. +func (cmd *ToolStateRequest) Do(c *Client) (*TemperatureStateResponse, error) { + uri := fmt.Sprintf("%s?history=%t&limit=%d", URIPrintTool, cmd.IncludeHistory, cmd.Limit) + + log.Printf("TODO-Remove: ToolStateRequest uri is: %s", uri) + //ToolStateRequest uri is: %s /api/printer/tool?history=true&limit=1 + /* + { + "history": [ + { + "tool0": { + "actual": 38.0, + "target": 0.0 + } + } + ], + "tool0": { + "actual": 38.0, + "offset": 0, + "target": 0.0 + } + } + */ + + b, err := c.doJSONRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + + r := &TemperatureStateResponse{} + if err := json.Unmarshal(b, &r); err != nil { + return nil, err + } + + return r, err +} + +// ToolTargetRequest sets the given target temperature on the printer’s tools. +type ToolTargetRequest struct { + // Target temperature(s) to set, key must match the format tool{n} with n + // being the tool’s index starting with 0. + Targets map[string]float64 `json:"targets"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolTargetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *ToolTargetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolTargetRequest + }{ + Command: "target", + ToolTargetRequest: *cmd, + }) +} + +// ToolOffsetRequest sets the given temperature offset on the printer’s tools. +type ToolOffsetRequest struct { + // Offset is offset(s) to set, key must match the format tool{n} with n + // being the tool’s index starting with 0. + Offsets map[string]float64 `json:"offsets"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolOffsetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *ToolOffsetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolOffsetRequest + }{ + Command: "offset", + ToolOffsetRequest: *cmd, + }) +} + +// ToolExtrudeRequest extrudes the given amount of filament from the currently +// selected tool. +type ToolExtrudeRequest struct { + // Amount is the amount of filament to extrude in mm. May be negative to + // retract. + Amount int `json:"amount"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolExtrudeRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *ToolExtrudeRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolExtrudeRequest + }{ + Command: "extrude", + ToolExtrudeRequest: *cmd, + }) +} + +// ToolSelectRequest selects the printer’s current tool. +type ToolSelectRequest struct { + // Tool to select, format tool{n} with n being the tool’s index starting + // with 0. + Tool string `json:"tool"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolSelectRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *ToolSelectRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolSelectRequest + }{ + Command: "select", + ToolSelectRequest: *cmd, + }) +} + + + + + + +// ToolFlowRateRequest changes the flow rate factor to apply to extrusion of the tool. +type ToolFlowRateRequest struct { + // Factor is the new factor, percentage as integer, between 75 and 125%. + Factor int `json:"factor"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolFlowRateRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *ToolFlowRateRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolFlowRateRequest + }{ + Command: "flowrate", + ToolFlowRateRequest: *cmd, + }) +} + + + + + + + + +// BedStateRequest retrieves the current temperature data (actual, target and +// offset) plus optionally a (limited) history (actual, target, timestamp) for +// the printer’s heated bed. +// +// It’s also possible to retrieve the temperature history by supplying the +// history query parameter set to true. The amount of returned history data +// points can be limited using the limit query parameter. +type BedStateRequest struct { + // History if true retrieve the temperature history. + IncludeHistory bool + + // Limit limtis amount of returned history data points. + Limit int +} + +// Do sends an API request and returns the API response. +func (cmd *BedStateRequest) Do(c *Client) (*TemperatureStateResponse, error) { + uri := fmt.Sprintf("%s?history=%t&limit=%d", URIPrintBed, cmd.IncludeHistory, cmd.Limit) + b, err := c.doJSONRequest("GET", uri, nil, PrintBedErrors) + if err != nil { + return nil, err + } + + r := &TemperatureStateResponse{} + if err := json.Unmarshal(b, &r); err != nil { + return nil, err + } + + return r, err +} + +// BedTargetRequest sets the given target temperature on the printer’s bed. +type BedTargetRequest struct { + // Target temperature to set. + Target float64 `json:"target"` +} + +// Do sends an API request and returns an error if any. +func (cmd *BedTargetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintBed, b, PrintBedErrors) + return err +} + +func (cmd *BedTargetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + BedTargetRequest + }{ + Command: "target", + BedTargetRequest: *cmd, + }) +} + +// BedOffsetRequest sets the given temperature offset on the printer’s bed. +type BedOffsetRequest struct { + // Offset is offset to set. + Offset int `json:"offset"` +} + +// Do sends an API request and returns an error if any. +func (cmd *BedOffsetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) + return err +} + +func (cmd *BedOffsetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + BedOffsetRequest + }{ + Command: "offset", + BedOffsetRequest: *cmd, + }) +} + +// CommandRequest sends any command to the printer via the serial interface. +// Should be used with some care as some commands can interfere with or even +// stop a running print job. +type CommandRequest struct { + // Commands list of commands to send to the printer. + Commands []string `json:"commands"` +} + +// Do sends an API request and returns an error if any. +func (cmd *CommandRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", URICommand, b, nil) + return err +} + +// CustomCommandsRequest retrieves all configured system controls. +type CustomCommandsRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *CustomCommandsRequest) Do(c *Client) (*CustomCommandsResponse, error) { + b, err := c.doJSONRequest("GET", URICommandCustom, nil, nil) + if err != nil { + return nil, err + } + + r := &CustomCommandsResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} + +// SDStateRequest retrieves the current state of the printer’s SD card. For this +// request no authentication is needed. +type SDStateRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *SDStateRequest) Do(c *Client) (*SDState, error) { + b, err := c.doJSONRequest("GET", URIPrintSD, nil, PrintSDErrors) + if err != nil { + return nil, err + } + + r := &SDState{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} + +// SDInitRequest initializes the printer’s SD card, making it available for use. +// This also includes an initial retrieval of the list of files currently stored +// on the SD card. +type SDInitRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SDInitRequest) Do(c *Client) error { + return doCommandRequest(c, URIPrintSD, "init", PrintSDErrors) +} + +// SDRefreshRequest Refreshes the list of files stored on the printer’s SD card. +type SDRefreshRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SDRefreshRequest) Do(c *Client) error { + return doCommandRequest(c, URIPrintSD, "refresh", PrintSDErrors) +} + +// SDReleaseRequest releases the SD card from the printer. The reverse operation +// to init. After issuing this command, the SD card won’t be available anymore, +// hence and operations targeting files stored on it will fail. +type SDReleaseRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SDReleaseRequest) Do(c *Client) error { + return doCommandRequest(c, URIPrintSD, "release", PrintSDErrors) +} + +// doCommandRequest can be used in any operation where the only required field +// is the `command` field. +func doCommandRequest(c *Client, uri, command string, m StatusMapping) error { + v := map[string]string{"command": command} + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(v); err != nil { + return err + } + + _, err := c.doJSONRequest("POST", uri, b, m) + return err +} diff --git a/octoprintApis/printer_test.go b/octoprintApis/printer_test.go new file mode 100755 index 00000000..31913b9c --- /dev/null +++ b/octoprintApis/printer_test.go @@ -0,0 +1,97 @@ +package octoprintApis + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestStateRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &StateRequest{} + state, err := r.Do(cli) + assert.NoError(t, err) + + assert.Equal(t, "Operational", state.State.Text) + assert.Len(t, state.Temperature.Current, 2) + assert.Len(t, state.Temperature.History, 0) +} + +func TestStateRequest_DoWithHistory(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &StateRequest{ + IncludeHistory: true, + } + state, err := r.Do(cli) + assert.NoError(t, err) + + assert.Equal(t, "Operational", state.State.Text) + assert.Len(t, state.Temperature.Current, 2) + assert.True(t, len(state.Temperature.History) > 0) +} + +func TestStateRequest_DoWithExclude(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &StateRequest{Exclude: []string{"temperature"}} + state, err := r.Do(cli) + assert.NoError(t, err) + + assert.Equal(t, "Operational", state.State.Text) + assert.Len(t, state.Temperature.Current, 0) +} + +func TestSDInitRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SDInitRequest{} + err := r.Do(cli) + assert.NoError(t, err) + + time.Sleep(50 * time.Millisecond) + + state, err := (&SDStateRequest{}).Do(cli) + assert.NoError(t, err) + assert.True(t, state.Ready) +} + +func TestSDReleaseRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SDReleaseRequest{} + err := r.Do(cli) + assert.NoError(t, err) + + state, err := (&SDStateRequest{}).Do(cli) + assert.NoError(t, err) + assert.False(t, state.Ready) +} + +func TestSDRefreshRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SDRefreshRequest{} + err := r.Do(cli) + assert.NoError(t, err) + + state, err := (&SDStateRequest{}).Do(cli) + assert.NoError(t, err) + assert.False(t, state.Ready) +} + +func TestCustomCommandsRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &CustomCommandsRequest{} + s, err := r.Do(cli) + assert.NoError(t, err) + + assert.Len(t, s.Controls, 1) + assert.Equal(t, s.Controls[0].Name, "Example for multiple commands") + assert.Len(t, s.Controls[0].Children, 1) + assert.Equal(t, s.Controls[0].Children[0].Name, "Move X (static)") + assert.Len(t, s.Controls[0].Children[0].Commands, 3) +} diff --git a/octoprintApis/settings.go b/octoprintApis/settings.go new file mode 100755 index 00000000..f676e04e --- /dev/null +++ b/octoprintApis/settings.go @@ -0,0 +1,23 @@ +package octoprintApis + +import "encoding/json" + +const URISettings = "/api/settings" + +// SettingsRequest retrieves the current configuration of OctoPrint. +type SettingsRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *SettingsRequest) Do(c *Client) (*SettingsResponse, error) { + bytes, err := c.doJSONRequest("GET", URISettings, nil, nil) + if err != nil { + return nil, err + } + + response := &SettingsResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/settings_test.go b/octoprintApis/settings_test.go new file mode 100644 index 00000000..32279325 --- /dev/null +++ b/octoprintApis/settings_test.go @@ -0,0 +1,17 @@ +package octoprintApis + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSettingsRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SettingsRequest{} + settings, err := r.Do(cli) + assert.NoError(t, err) + + assert.Equal(t, settings.API.Enabled, true) +} diff --git a/octoprintApis/system.go b/octoprintApis/system.go new file mode 100755 index 00000000..f9e7844c --- /dev/null +++ b/octoprintApis/system.go @@ -0,0 +1,59 @@ +package octoprintApis + +import ( + "encoding/json" + "fmt" +) + +var ExecuteErrors = StatusMapping{ + 404: "The command could not be found for source and action", + 500: "The command didn’t define a command to execute, the command returned a non-zero return code and ignore was not true or some other internal server error occurred", +} + +const URISystemCommands = "/api/system/commands" + +// SystemCommandsRequest retrieves all configured system commands. +type SystemCommandsRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *SystemCommandsRequest) Do(c *Client) (*SystemCommandsResponse, error) { + b, err := c.doJSONRequest("GET", URISystemCommands, nil, nil) + if err != nil { + return nil, err + } + + r := &SystemCommandsResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + for i := range r.Core { + x := r.Core[i] + if err2 := json.Unmarshal(x.RawConfirm, x.Confirm); err2 != nil { + x.Confirm = "" + } + } + for i := range r.Custom { + x := r.Custom[i] + if err2 := json.Unmarshal(x.RawConfirm, x.Confirm); err2 != nil { + x.Confirm = "" + } + } + + return r, err +} + +// SystemExecuteCommandRequest retrieves all configured system commands. +type SystemExecuteCommandRequest struct { + // Source for which to list commands. + Source CommandSource `json:"source"` + + // Action is the identifier of the command, action from its definition. + Action string `json:"action"` +} + +// Do sends an API request and returns an error if any. +func (cmd *SystemExecuteCommandRequest) Do(c *Client) error { + uri := fmt.Sprintf("%s/%s/%s", URISystemCommands, cmd.Source, cmd.Action) + _, err := c.doJSONRequest("POST", uri, nil, ExecuteErrors) + return err +} diff --git a/octoprintApis/system_test.go b/octoprintApis/system_test.go new file mode 100644 index 00000000..b99cab6d --- /dev/null +++ b/octoprintApis/system_test.go @@ -0,0 +1,31 @@ +package octoprintApis + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSystemCommandsRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SystemCommandsRequest{} + state, err := r.Do(cli) + assert.NoError(t, err) + + assert.Len(t, state.Core, 1) + assert.Len(t, state.Custom, 0) + assert.Equal(t, "shutdown", state.Core[0].Action) +} + +func TestSystemExecuteCommandRequest_Do(t *testing.T) { + cli := NewClient("http://localhost:5000", "") + + r := &SystemExecuteCommandRequest{} + err := r.Do(cli) + assert.Error(t, err) + + r = &SystemExecuteCommandRequest{Source: Core, Action: "shutdown"} + err = r.Do(cli) + assert.NoError(t, err) +} diff --git a/octoprintApis/version.go b/octoprintApis/version.go new file mode 100644 index 00000000..1a68a9aa --- /dev/null +++ b/octoprintApis/version.go @@ -0,0 +1,25 @@ +package octoprintApis + +import ( + "encoding/json" +) + +const URIVersion = "/api/version" + +// VersionRequest retrieve information regarding server and API version. +type VersionRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *VersionRequest) Do(c *Client) (*VersionResponse, error) { + b, err := c.doJSONRequest("GET", URIVersion, nil, nil) + if err != nil { + return nil, err + } + + r := &VersionResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/zbolt.go b/octoprintApis/zbolt.go new file mode 100755 index 00000000..b0381637 --- /dev/null +++ b/octoprintApis/zbolt.go @@ -0,0 +1,148 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "fmt" + "log" +) + +const URIZBoltRequest = "/api/plugin/zbolt" +const URIZBoltOctoScreenRequest = "/api/plugin/zbolt_octoscreen" + +type RunZOffsetCalibrationRequest struct { + Command string `json:"command"` +} + +func (cmd *RunZOffsetCalibrationRequest) Do(c *Client) error { + cmd.Command = "run_zoffset_calibration" + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + log.Println("zbolt.Do() 1 - NewEncoder() failed") + return err + } + + _, err := c.doJSONRequest("POST", URIZBoltRequest, b, ConnectionErrors) + return err +} + +// SetZOffsetRequest - retrieves the current configuration of OctoPrint. +type SetZOffsetRequest struct { + Command string `json:"command"` + Tool int `json:"tool"` + Value float64 `json:"value"` +} + +func (cmd *SetZOffsetRequest) Do(c *Client) error { + cmd.Command = "set_z_offset" + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + log.Println("zbolt.Do() 2 - Encode() failed") + return err + } + + _, err := c.doJSONRequest("POST", URIZBoltRequest, b, ConnectionErrors) + return err +} + +type GetZOffsetRequest struct { + Command string `json:"command"` + Tool int `json:"tool"` +} + +type GetZOffsetResponse struct { + // Job contains information regarding the target of the current print job. + Offset float64 `json:"offset"` +} + +func (cmd *GetZOffsetRequest) Do(c *Client) (*GetZOffsetResponse, error) { + cmd.Command = "get_z_offset" + + params := bytes.NewBuffer(nil) + if err := json.NewEncoder(params).Encode(cmd); err != nil { + log.Println("zbolt.Do() 3 - Encode() failed") + return nil, err + } + + // b, err := c.doJSONRequest("POST", URIZBoltRequest, params, ConnectionErrors) + b, err := c.doJSONRequest("GET", URIZBoltRequest, params, ConnectionErrors) + if err != nil { + log.Println("zbolt.Do() 3 - doJSONRequest() failed") + return nil, err + } + + r := &GetZOffsetResponse{} + if err := json.Unmarshal(b, r); err != nil { + log.Println("zbolt.Do() 3 - Unmarshal() failed") + return nil, err + } + + return r, err +} + +type GetNotificationRequest struct { + Command string `json:"command"` +} + +type GetNotificationResponse struct { + // Job contains information regarding the target of the current print job. + Message string `json:"message"` +} + +func (cmd *GetNotificationRequest) Do(c *Client) (*GetNotificationResponse, error) { + target := fmt.Sprintf("%s?command=get_notification", URIZBoltOctoScreenRequest) + bytes, err := c.doJSONRequest("GET", target, nil, ConnectionErrors) + if err != nil { + return nil, err + } + + response := &GetNotificationResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} + + +type GetSettingsRequest struct { + Command string `json:"command"` +} + +type MenuItem struct { + Name string `json:"name"` + Icon string `json:"icon"` + Panel string `json:"panel"` + Items []MenuItem `json:"items"` +} + +type GetSettingsResponse struct { + // Job contains information regarding the target of the current print job. + FilamentInLength float64 `json:"filament_in_length"` + FilamentOutLength float64 `json:"filament_out_length"` + ToolChanger bool `json:"toolchanger"` + XAxisInverted bool `json:"x_axis_inverted"` + YAxisInverted bool `json:"y_axis_inverted"` + ZAxisInverted bool `json:"z_axis_inverted"` + MenuStructure []MenuItem `json:"menu_structure"` + GCodes struct { + AutoBedLevel string `json:"auto_bed_level"` + } `json:"gcodes"` +} + +func (cmd *GetSettingsRequest) Do(c *Client) (*GetSettingsResponse, error) { + target := fmt.Sprintf("%s?command=get_settings", URIZBoltOctoScreenRequest) + bytes, err := c.doJSONRequest("GET", target, nil, ConnectionErrors) + if err != nil { + return nil, err + } + + response := &GetSettingsResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/ui/BedLevelPanel.go b/ui/BedLevelPanel.go index bf1189f0..7f608cbc 100755 --- a/ui/BedLevelPanel.go +++ b/ui/BedLevelPanel.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -106,7 +106,7 @@ func (this *bedLevelPanel) addBedLevelCornerButton(isLeft, isTop bool) { func (this *bedLevelPanel) defineLevelingPoints() { utils.Logger.Debug("entering BedLevelPanel.verifyConnection()") - connectionRequest, err := (&octoprint.ConnectionRequest{}).Do(this.UI.Client) + connectionRequest, err := (&octoprintApis.ConnectionRequest{}).Do(this.UI.Client) if err != nil { utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(ConnectionRequest)", err) @@ -116,7 +116,7 @@ func (this *bedLevelPanel) defineLevelingPoints() { utils.Logger.Info(connectionRequest.Current.PrinterProfile) - printerProfile, err := (&octoprint.PrinterProfilesRequest{Id: connectionRequest.Current.PrinterProfile}).Do(this.UI.Client) + printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionRequest.Current.PrinterProfile}).Do(this.UI.Client) if err != nil { utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(PrinterProfilesRequest)", err) @@ -145,7 +145,7 @@ func (this *bedLevelPanel) createLevelButton(placement string) *gtk.Button { button := utils.MustButtonImage(noLabel, imageFileName, func() { this.goHomeIfRequired() - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string { "G0 Z10 F2000", fmt.Sprintf("G0 X%f Y%f F10000", this.points[placement][0], this.points[placement][1]), @@ -166,7 +166,7 @@ func (this *bedLevelPanel) goHomeIfRequired() { return } - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{ "G28", } @@ -181,7 +181,7 @@ func (this *bedLevelPanel) goHomeIfRequired() { func (this *bedLevelPanel) createAutoLevelButton(gcode string) *gtk.Button { button := utils.MustButtonImage("Auto Level", "bed-level.svg", func() { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{ gcode, } diff --git a/ui/CommonPanel.go b/ui/CommonPanel.go index c030c337..ab40fbc3 100755 --- a/ui/CommonPanel.go +++ b/ui/CommonPanel.go @@ -9,8 +9,8 @@ import ( // "github.com/gotk3/gotk3/glib" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -106,7 +106,7 @@ func (this *CommonPanel) Scaled(s int) int { func (this *CommonPanel) arrangeMenuItems( grid *gtk.Grid, - items []octoprint.MenuItem, + items []octoprintApis.MenuItem, cols int, ) { for i, item := range items { @@ -123,7 +123,7 @@ func (this *CommonPanel) arrangeMenuItems( } func (this *CommonPanel) command(gcode string) error { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{gcode} return cmd.Do(this.UI.Client) } diff --git a/ui/ControlPanel.go b/ui/ControlPanel.go index 7f981b90..f7370cf0 100755 --- a/ui/ControlPanel.go +++ b/ui/ControlPanel.go @@ -4,8 +4,8 @@ import ( "strings" // "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -51,8 +51,8 @@ func (this *controlPanel) initialize() { } } -func (this *controlPanel) getDefaultControls() []*octoprint.ControlDefinition { - var controlDefinitions = []*octoprint.ControlDefinition{{ +func (this *controlPanel) getDefaultControls() []*octoprintApis.ControlDefinition { + var controlDefinitions = []*octoprintApis.ControlDefinition{{ Name: "Motor Off", Command: "M18", // Disable all stepper motors immediately }, { @@ -69,11 +69,11 @@ func (this *controlPanel) getDefaultControls() []*octoprint.ControlDefinition { return controlDefinitions } -func (this *controlPanel) getCustomControls() []*octoprint.ControlDefinition { - controlDefinitions := []*octoprint.ControlDefinition{} +func (this *controlPanel) getCustomControls() []*octoprintApis.ControlDefinition { + controlDefinitions := []*octoprintApis.ControlDefinition{} utils.Logger.Info("control.getCustomControl() - Retrieving custom controls") - response, err := (&octoprint.CustomCommandsRequest{}).Do(this.UI.Client) + response, err := (&octoprintApis.CustomCommandsRequest{}).Do(this.UI.Client) if err != nil { utils.LogError("control.getCustomControl()", "Do(ControlDefinition)", err) return controlDefinitions @@ -90,9 +90,9 @@ func (this *controlPanel) getCustomControls() []*octoprint.ControlDefinition { return controlDefinitions } -func (this *controlPanel) getCommands() []*octoprint.CommandDefinition { +func (this *controlPanel) getCommands() []*octoprintApis.CommandDefinition { utils.Logger.Info("Retrieving custom commands") - response, err := (&octoprint.SystemCommandsRequest{}).Do(this.UI.Client) + response, err := (&octoprintApis.SystemCommandsRequest{}).Do(this.UI.Client) if err != nil { utils.LogError("control.getCommands()", "Do(SystemCommandsRequest)", err) return nil diff --git a/ui/CustomItemsPanel.go b/ui/CustomItemsPanel.go index a3101f3f..2572f26a 100755 --- a/ui/CustomItemsPanel.go +++ b/ui/CustomItemsPanel.go @@ -1,20 +1,20 @@ package ui import ( - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) type customItemsPanel struct { CommonPanel - items []octoprint.MenuItem + items []octoprintApis.MenuItem } func CustomItemsPanel( ui *UI, parentPanel interfaces.IPanel, - items []octoprint.MenuItem, + items []octoprintApis.MenuItem, ) *customItemsPanel { instance := &customItemsPanel { CommonPanel: NewCommonPanel(ui, parentPanel), diff --git a/ui/FanPanel.go b/ui/FanPanel.go index 91087ddf..ea02e5c0 100755 --- a/ui/FanPanel.go +++ b/ui/FanPanel.go @@ -4,7 +4,6 @@ import ( // "fmt" // "github.com/gotk3/gotk3/gtk" - // "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/uiWidgets" // "github.com/Z-Bolt/OctoScreen/utils" diff --git a/ui/FilamentPanel.go b/ui/FilamentPanel.go index 68d494bb..b66686f6 100755 --- a/ui/FilamentPanel.go +++ b/ui/FilamentPanel.go @@ -6,7 +6,6 @@ import ( // "time" "github.com/gotk3/gotk3/gtk" - // "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index c42098d1..962a741d 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -8,8 +8,8 @@ import ( "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -29,7 +29,7 @@ func FilesPanel( ) *filesPanel { if filesPanelInstance == nil { locationHistory := utils.LocationHistory { - Locations: []octoprint.Location{}, + Locations: []octoprintApis.Location{}, } instance := &filesPanel { @@ -106,8 +106,8 @@ func (this *filesPanel) doLoadFiles() { this.listBox.ShowAll() } -func (this *filesPanel) getSortedFiles() []*octoprint.FileResponse { - var files []*octoprint.FileResponse +func (this *filesPanel) getSortedFiles() []*octoprintApis.FileResponse { + var files []*octoprintApis.FileResponse length := this.locationHistory.Length() if length < 1 { @@ -117,19 +117,19 @@ func (this *filesPanel) getSortedFiles() []*octoprint.FileResponse { current := this.locationHistory.CurrentLocation() utils.Logger.Info("Loading list of files from: ", string(current)) - filesRequest := &octoprint.FilesRequest { + filesRequest := &octoprintApis.FilesRequest { Location: current, Recursive: false, } filesResponse, err := filesRequest.Do(this.UI.Client) if err != nil { utils.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) - files = []*octoprint.FileResponse{} + files = []*octoprintApis.FileResponse{} } else { files = filesResponse.Files } - var filteredFiles []*octoprint.FileResponse + var filteredFiles []*octoprintApis.FileResponse for i := range files { if !strings.HasPrefix(files[i].Path, "trash") { filteredFiles = append(filteredFiles, files[i]) @@ -145,8 +145,8 @@ func (this *filesPanel) getSortedFiles() []*octoprint.FileResponse { func (this *filesPanel) addRootLocations() { this.addMessage("Select source location:") - this.addRootLocation(octoprint.Local, 0) - this.addRootLocation(octoprint.SDCard, 1) + this.addRootLocation(octoprintApis.Local, 0) + this.addRootLocation(octoprintApis.SDCard, 1) } func (this *filesPanel) addMessage(message string) { @@ -165,9 +165,9 @@ func (this *filesPanel) addMessage(message string) { this.listBox.Add(listItemFrame) } -func (this *filesPanel) addRootLocation(location octoprint.Location, index int) { +func (this *filesPanel) addRootLocation(location octoprintApis.Location, index int) { var itemImage *gtk.Image - if location == octoprint.Local { + if location == octoprintApis.Local { itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) } else { itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) @@ -177,7 +177,7 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) topBox.Add(itemImage) name := "" - if location == octoprint.Local { + if location == octoprintApis.Local { name = " OctoPrint" } else { name = " SD Card" @@ -193,7 +193,7 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) var itemButton *gtk.Button - if location == octoprint.Local { + if location == octoprintApis.Local { itemButton = this.createOpenLocationButton(location) } else { itemButton = this.createOpenLocationButton(location) @@ -212,7 +212,7 @@ func (this *filesPanel) addRootLocation(location octoprint.Location, index int) this.listBox.Add(listItemFrame) } -func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileResponse) { +func (this *filesPanel) addSortedFiles(sortedFiles []*octoprintApis.FileResponse) { var index int = 0 for _, fileResponse := range sortedFiles { @@ -231,7 +231,7 @@ func (this *filesPanel) addSortedFiles(sortedFiles []*octoprint.FileResponse) { } -func (this *filesPanel) addItem(fileResponse *octoprint.FileResponse, index int) { +func (this *filesPanel) addItem(fileResponse *octoprintApis.FileResponse, index int) { isFolder := fileResponse.IsFolder() var itemImage *gtk.Image @@ -332,7 +332,7 @@ func (this *filesPanel) createListItemBox() *gtk.Box { return listItemBox } -func (this *filesPanel) addThumbnail(fileResponse *octoprint.FileResponse, listItemBox *gtk.Box) { +func (this *filesPanel) addThumbnail(fileResponse *octoprintApis.FileResponse, listItemBox *gtk.Box) { if fileResponse.Thumbnail != "" { utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) @@ -365,11 +365,11 @@ func (this *filesPanel) addThumbnail(fileResponse *octoprint.FileResponse, listI } -func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *gtk.Button { +func (this *filesPanel) createOpenLocationButton(location octoprintApis.Location) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { this.locationHistory = utils.LocationHistory { - Locations: []octoprint.Location{location}, + Locations: []octoprintApis.Location{location}, } this.doLoadFiles() @@ -382,7 +382,7 @@ func (this *filesPanel) createOpenLocationButton(location octoprint.Location) *g return button } -func (this *filesPanel) createOpenFolderButton(fileResponse *octoprint.FileResponse) *gtk.Button { +func (this *filesPanel) createOpenFolderButton(fileResponse *octoprintApis.FileResponse) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { this.locationHistory.GoForward(fileResponse.Name) @@ -396,11 +396,11 @@ func (this *filesPanel) createOpenFolderButton(fileResponse *octoprint.FileRespo return button } -func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *octoprint.FileResponse) *gtk.Button { +func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *octoprintApis.FileResponse) *gtk.Button { button := utils.MustButton( utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { - selectFileRequest := &octoprint.SelectFileRequest{} + selectFileRequest := &octoprintApis.SelectFileRequest{} // Set the location to "local" or "sdcard" selectFileRequest.Location = this.locationHistory.Locations[0] @@ -425,7 +425,7 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileRespo /* func (this *filesPanel) isReady() bool { - state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client) + state, err := (&octoprintApis.SDStateRequest{}).Do(this.UI.Client) if err != nil { Logger.Error(err) return false diff --git a/ui/HomePanel.go b/ui/HomePanel.go index 9447ec24..374f8e78 100755 --- a/ui/HomePanel.go +++ b/ui/HomePanel.go @@ -2,8 +2,8 @@ package ui import ( // "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" // "github.com/Z-Bolt/OctoScreen/utils" ) @@ -32,13 +32,13 @@ func HomePanel( func (this *homePanel) initialize() { defer this.Initialize() - homeXButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home X", "home-x.svg", octoprint.XAxis) + homeXButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home X", "home-x.svg", octoprintApis.XAxis) this.Grid().Attach(homeXButton, 2, 1, 1, 1) - homeYButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Y", "home-y.svg", octoprint.YAxis) + homeYButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Y", "home-y.svg", octoprintApis.YAxis) this.Grid().Attach(homeYButton, 1, 0, 1, 1) - homeZButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Z", "home-z.svg", octoprint.ZAxis) + homeZButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Z", "home-z.svg", octoprintApis.ZAxis) this.Grid().Attach(homeZButton, 1, 1, 1, 1) homeAllButton := uiWidgets.CreateHomeAllButton(this.UI.Client) diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go index 25f85b3c..9d91caaf 100755 --- a/ui/IdleStatusPanel.go +++ b/ui/IdleStatusPanel.go @@ -5,7 +5,7 @@ import ( // "sync" "time" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -41,7 +41,7 @@ func (this *idleStatusPanel) initialize() { utils.Logger.Info(this.UI.Settings) - var menuItems []octoprint.MenuItem + var menuItems []octoprintApis.MenuItem if this.UI.Settings == nil || this.UI.Settings.MenuStructure == nil || len(this.UI.Settings.MenuStructure) < 1 { utils.Logger.Info("Loading default menu") this.UI.Settings.MenuStructure = getDefaultMenuItems(this.UI.Client) @@ -118,7 +118,7 @@ func (this *idleStatusPanel) showTools() { func (this *idleStatusPanel) updateTemperature() { utils.Logger.Debug("entering IdleStatusPanel.updateTemperature()") - fullStateResponse, err := (&octoprint.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) + fullStateResponse, err := (&octoprintApis.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) if err != nil { utils.LogError("IdleStatusPanel.updateTemperature()", "Do(StateRequest)", err) diff --git a/ui/MovePanel.go b/ui/MovePanel.go index 62b534ed..29f874a1 100755 --- a/ui/MovePanel.go +++ b/ui/MovePanel.go @@ -1,11 +1,9 @@ package ui import ( - // "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" - // "github.com/Z-Bolt/OctoScreen/utils" ) var movePanelInstance *movePanel @@ -44,27 +42,27 @@ func (this *movePanel) initialize() { } if xAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprint.XAxis, 1), 0, 1, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprint.XAxis, -1), 2, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprintApis.XAxis, 1), 0, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprintApis.XAxis, -1), 2, 1, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprint.XAxis, -1), 0, 1, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprint.XAxis, 1), 2, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprintApis.XAxis, -1), 0, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprintApis.XAxis, 1), 2, 1, 1, 1) } if yAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprint.YAxis, -1), 1, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprint.YAxis, 1), 1, 2, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprintApis.YAxis, -1), 1, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprintApis.YAxis, 1), 1, 2, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprint.YAxis, 1), 1, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprint.YAxis, -1), 1, 2, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprintApis.YAxis, 1), 1, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprintApis.YAxis, -1), 1, 2, 1, 1) } if zAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprint.ZAxis, -1), 3, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprint.ZAxis, 1), 3, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprintApis.ZAxis, -1), 3, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprintApis.ZAxis, 1), 3, 1, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprint.ZAxis, 1), 3, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprint.ZAxis, -1), 3, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprintApis.ZAxis, 1), 3, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprintApis.ZAxis, -1), 3, 1, 1, 1) } this.Grid().Attach(this.amountToMoveStepButton, 1, 1, 1, 1) diff --git a/ui/PrintStatusPanel.go b/ui/PrintStatusPanel.go index 4a908d73..3143a7d0 100755 --- a/ui/PrintStatusPanel.go +++ b/ui/PrintStatusPanel.go @@ -6,8 +6,8 @@ import ( "time" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -157,7 +157,7 @@ func (this *printStatusPanel) createPauseButton() gtk.IWidget { defer this.updateTemperature() utils.Logger.Info("Pausing/Resuming job") - cmd := &octoprint.PauseRequest{Action: octoprint.Toggle} + cmd := &octoprintApis.PauseRequest{Action: octoprintApis.Toggle} err := cmd.Do(this.UI.Client) utils.Logger.Info("Pausing/Resuming job 2, Do() was just called") @@ -207,7 +207,7 @@ func (this *printStatusPanel) update() { func (this *printStatusPanel) updateTemperature() { //Logger.Printf("Now in print_status.updateTemperature()") - fullStateResponse, err := (&octoprint.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) + fullStateResponse, err := (&octoprintApis.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) if err != nil { utils.LogError("print_status.updateTemperature()", "Do(StateRequest)", err) return @@ -238,7 +238,7 @@ func (this *printStatusPanel) updateTemperature() { //Logger.Printf("Now leaving print_status.updateTemperature()") } -func (this *printStatusPanel) doUpdateState(printerState *octoprint.PrinterState) { +func (this *printStatusPanel) doUpdateState(printerState *octoprintApis.PrinterState) { switch { case printerState.Flags.Printing: this.pauseButton.SetSensitive(true) @@ -298,7 +298,7 @@ func (this *printStatusPanel) doUpdateState(printerState *octoprint.PrinterState func (this *printStatusPanel) updateJob() { //Logger.Printf("Now in print_status.updateJob()") - jobResponse, err := (&octoprint.JobRequest{}).Do(this.UI.Client) + jobResponse, err := (&octoprintApis.JobRequest{}).Do(this.UI.Client) if err != nil { utils.LogError("print_status.updateJob()", "Do(JobRequest)", err) return @@ -308,11 +308,17 @@ func (this *printStatusPanel) updateJob() { if jobResponse.Job.File.Name != "" { jobFileName = jobResponse.Job.File.Name jobFileName = strings.Replace(jobFileName, ".gcode", "", -1) - jobFileName = utils.StrEllipsisLen(jobFileName, 20) + jobFileName = utils.TruncateString(jobFileName, 20) } this.fileLabel.Label.SetLabel(jobFileName) this.progressBar.SetFraction(jobResponse.Progress.Completion / 100) + // strProgress := fmd.Sprintf("%d%% L=%d/%d", + // jobResponse.Progress.Completion / 100, + // jobResponse.Progress, + // ) + // this.progressBar.SetText(strProgress) + var timeSpent, timeLeft string switch jobResponse.Progress.Completion { @@ -367,7 +373,7 @@ func confirmStopDialogBox( userResponse := dialogBox.Run() if userResponse == int(gtk.RESPONSE_YES) { utils.Logger.Warning("Stopping job") - if err := (&octoprint.CancelRequest{}).Do(printStatusPanel.UI.Client); err != nil { + if err := (&octoprintApis.CancelRequest{}).Do(printStatusPanel.UI.Client); err != nil { utils.LogError("print_status.confirmStopDialogBox()", "Do(CancelRequest)", err) return } diff --git a/ui/TemperaturePresetsPanel.go b/ui/TemperaturePresetsPanel.go index 1e5557ef..9ace3414 100755 --- a/ui/TemperaturePresetsPanel.go +++ b/ui/TemperaturePresetsPanel.go @@ -1,8 +1,8 @@ package ui import ( - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -37,7 +37,7 @@ func (this *temperaturePresetsPanel) initialize() { } func (this *temperaturePresetsPanel) createTemperaturePresetButtons() { - settings, err := (&octoprint.SettingsRequest{}).Do(this.UI.Client) + settings, err := (&octoprintApis.SettingsRequest{}).Do(this.UI.Client) if err != nil { utils.LogError("TemperaturePresetsPanel.getTemperaturePresets()", "Do(SettingsRequest)", err) return diff --git a/ui/menu.go b/ui/menu.go index c6ab9219..da7d8119 100755 --- a/ui/menu.go +++ b/ui/menu.go @@ -3,16 +3,15 @@ package ui import ( "encoding/json" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" - // "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) func getPanel( ui *UI, parentPanel interfaces.IPanel, - menuItem octoprint.MenuItem, + menuItem octoprintApis.MenuItem, ) interfaces.IPanel { switch menuItem.Panel { // The standard "top four" panels that are in the idleStatus panel @@ -99,7 +98,7 @@ func getPanel( } } -func getDefaultMenuItems(client *octoprint.Client) []octoprint.MenuItem { +func getDefaultMenuItems(client *octoprintApis.Client) []octoprintApis.MenuItem { defaultMenuItemsForSingleToolhead := `[ { "name": "Home", @@ -206,7 +205,7 @@ func getDefaultMenuItems(client *octoprint.Client) []octoprint.MenuItem { ]` - var menuItems []octoprint.MenuItem + var menuItems []octoprintApis.MenuItem var err error toolheadCount := utils.GetToolheadCount(client) diff --git a/ui/tool_changer_panel.go b/ui/tool_changer_panel.go index c7080d6b..627eb326 100755 --- a/ui/tool_changer_panel.go +++ b/ui/tool_changer_panel.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -55,7 +55,7 @@ func (this *toolChangerPanel) createZCalibrationButton() gtk.IWidget { func (this *toolChangerPanel) createMagnetOnButton() gtk.IWidget { return utils.MustButtonImageStyle("Magnet On", "magnet-on.svg", "", func() { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{"SET_PIN PIN=sol VALUE=1"} utils.Logger.Info("Turn on magnet") @@ -68,7 +68,7 @@ func (this *toolChangerPanel) createMagnetOnButton() gtk.IWidget { func (this *toolChangerPanel) createMagnetOffButton() gtk.IWidget { return utils.MustButtonImageStyle("Magnet Off", "magnet-off.svg", "", func() { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{"SET_PIN PIN=sol VALUE=0"} utils.Logger.Info("Turn off magnet") diff --git a/ui/ui.go b/ui/ui.go index ed17ebee..dd6c5887 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -10,9 +10,8 @@ import ( "github.com/golang-collections/collections/stack" "github.com/gotk3/gotk3/gdk" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" - "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -21,9 +20,9 @@ type UI struct { sync.Mutex PanelHistory *stack.Stack - Client *octoprint.Client - ConnectionState octoprint.ConnectionState - Settings *octoprint.GetSettingsResponse + Client *octoprintApis.Client + ConnectionState octoprintApis.ConnectionState + Settings *octoprintApis.GetSettingsResponse UIState string @@ -53,7 +52,7 @@ func New(endpoint, key string, width, height int) *UI { instance := &UI{ PanelHistory: stack.New(), - Client: octoprint.NewClient(endpoint, key), + Client: octoprintApis.NewClient(endpoint, key), NotificationsBox: uiWidgets.NewNotificationsBox(), OctoPrintPluginIsAvailable: true, Settings: nil, @@ -156,7 +155,7 @@ func (this *UI) verifyConnection() { newUIState := "<>" splashMessage := "<>" - connectionResponse, err := (&octoprint.ConnectionRequest{}).Do(this.Client) + connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) if err == nil { this.ConnectionState = connectionResponse.Current.State strCurrentState := string(connectionResponse.Current.State) @@ -174,7 +173,7 @@ func (this *UI) verifyConnection() { fallthrough case connectionResponse.Current.State.IsOffline(): newUIState = "splash" - if err := (&octoprint.ConnectRequest{}).Do(this.Client); err != nil { + if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { utils.LogError("ui.verifyConnection()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) splashMessage = "Loading..." } else { @@ -270,7 +269,7 @@ func (this *UI) checkNotification() { return } - notificationRespone, err := (&octoprint.GetNotificationRequest{}).Do(this.Client) + notificationRespone, err := (&octoprintApis.GetNotificationRequest{}).Do(this.Client) if err != nil { utils.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) utils.Logger.Debug("leaving ui.checkNotification()") @@ -287,7 +286,7 @@ func (this *UI) checkNotification() { func (this *UI) loadSettings() { utils.Logger.Debug("entering ui.loadSettings()") - settingsResponse, err := (&octoprint.GetSettingsRequest{}).Do(this.Client) + settingsResponse, err := (&octoprintApis.GetSettingsRequest{}).Do(this.Client) if err != nil { text := err.Error() if strings.Contains(strings.ToLower(text), "unexpected status code: 404") { @@ -316,7 +315,7 @@ func (this *UI) loadSettings() { utils.Logger.Debug("leaving ui.loadSettings()") } -func (this *UI) validateMenuItems(menuItems []octoprint.MenuItem, name string, isRoot bool) bool { +func (this *UI) validateMenuItems(menuItems []octoprintApis.MenuItem, name string, isRoot bool) bool { if menuItems == nil { return true } @@ -381,7 +380,7 @@ func (this *UI) update() { this.loadSettings() if this.Settings == nil { - this.Settings = &octoprint.GetSettingsResponse { + this.Settings = &octoprintApis.GetSettingsResponse { FilamentInLength: 750.0, FilamentOutLength: 800.0, ToolChanger: false, diff --git a/ui/z_offset_calibration_panel.go b/ui/z_offset_calibration_panel.go index 2194a902..425623ee 100755 --- a/ui/z_offset_calibration_panel.go +++ b/ui/z_offset_calibration_panel.go @@ -6,8 +6,8 @@ import ( "time" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -114,7 +114,7 @@ func (this *zOffsetCalibrationPanel) selectToolStepButtonHandleClick() { time.Sleep(time.Second * 1) this.command(fmt.Sprintf("G0 X%f Y%f F10000", this.cPoint.x, this.cPoint.y)) - cmd := &octoprint.GetZOffsetRequest{Tool: this.activeTool} + cmd := &octoprintApis.GetZOffsetRequest{Tool: this.activeTool} response, err := cmd.Do(this.UI.Client) if err != nil { utils.LogError("z_offset_calibration.setToolheadButtonClickHandler()", "Do(GetZOffsetRequest)", err) @@ -214,7 +214,7 @@ func (this *zOffsetCalibrationPanel) CreateAutoZCalibrationButton() gtk.IWidget // BUG: This does not work. At least not on a Prusa i3. Need to get this working with all printers. // when RunZOffsetCalibrationRequest is called, it's returning a 404. - cmd := &octoprint.RunZOffsetCalibrationRequest{} + cmd := &octoprintApis.RunZOffsetCalibrationRequest{} if err := cmd.Do(this.UI.Client); err != nil { utils.LogError("z_offset_calibration.createAutoZCalibrationButton()", "Do(RunZOffsetCalibrationRequest)", err) } @@ -228,7 +228,7 @@ func (this *zOffsetCalibrationPanel) updateZOffset(value float64) { this.zOffsetLabel.SetText(fmt.Sprintf("Z-Offset: %.2f", this.zOffset)) - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string { fmt.Sprintf("SET_GCODE_OFFSET Z=%f", this.zOffset), "G0 Z0 F100", @@ -237,7 +237,7 @@ func (this *zOffsetCalibrationPanel) updateZOffset(value float64) { utils.LogError("z_offset_calibration.updateZOffset()", "Do(CommandRequest)", err) } - cmd2 := &octoprint.SetZOffsetRequest { + cmd2 := &octoprintApis.SetZOffsetRequest { Value: this.zOffset, Tool: this.activeTool, } @@ -248,7 +248,7 @@ func (this *zOffsetCalibrationPanel) updateZOffset(value float64) { func (this *zOffsetCalibrationPanel) command(gcode string) error { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{gcode} return cmd.Do(this.UI.Client) diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index c59a6dd9..91e7dacc 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -4,22 +4,22 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type CommandButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client parentWindow *gtk.Window - commandDefinition *octoprint.CommandDefinition + commandDefinition *octoprintApis.CommandDefinition } func CreateCommandButton( - client *octoprint.Client, + client *octoprintApis.Client, parentWindow *gtk.Window, - commandDefinition *octoprint.CommandDefinition, + commandDefinition *octoprintApis.CommandDefinition, iconName string, ) *CommandButton { base := utils.MustButtonImage(utils.StrEllipsisLen(commandDefinition.Name, 16), iconName + ".svg", nil) @@ -47,8 +47,8 @@ func (this *CommandButton) handleClicked() { } func (this *CommandButton) sendCommand() { - commandRequest := &octoprint.SystemExecuteCommandRequest{ - Source: octoprint.Custom, + commandRequest := &octoprintApis.SystemExecuteCommandRequest{ + Source: octoprintApis.Custom, Action: this.commandDefinition.Action, } diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index 8b36d49c..5f8a0ec1 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -4,22 +4,22 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type ControlButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client parentWindow *gtk.Window - controlDefinition *octoprint.ControlDefinition + controlDefinition *octoprintApis.ControlDefinition } func CreateControlButton( - client *octoprint.Client, + client *octoprintApis.Client, parentWindow *gtk.Window, - controlDefinition *octoprint.ControlDefinition, + controlDefinition *octoprintApis.ControlDefinition, iconName string, ) *ControlButton { base := utils.MustButtonImage(utils.StrEllipsisLen(controlDefinition.Name, 16), iconName + ".svg", nil) @@ -47,7 +47,7 @@ func (this *ControlButton) handleClicked() { } func (this *ControlButton) sendCommand() { - commandRequest := &octoprint.CommandRequest{ + commandRequest := &octoprintApis.CommandRequest{ Commands: this.controlDefinition.Commands, } diff --git a/uiWidgets/CoolDownButton.go b/uiWidgets/CoolDownButton.go index f10a5cbb..b6198aec 100755 --- a/uiWidgets/CoolDownButton.go +++ b/uiWidgets/CoolDownButton.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -12,12 +12,12 @@ import ( type CoolDownButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client callback func() } func CreateCoolDownButton( - client *octoprint.Client, + client *octoprintApis.Client, callback func(), ) *CoolDownButton { base := utils.MustButtonImage("All Off", "cool-down.svg", nil) @@ -44,10 +44,10 @@ func (this *CoolDownButton) handleClicked() { } func TurnAllHeatersOff( - client *octoprint.Client, + client *octoprintApis.Client, ) { // Set the bed's temp. - bedTargetRequest := &octoprint.BedTargetRequest{Target: 0.0} + bedTargetRequest := &octoprintApis.BedTargetRequest{Target: 0.0} err := bedTargetRequest.Do(client) if err != nil { utils.LogError("CoolDownButton.handleClicked()", "Do(BedTargetRequest)", err) @@ -57,7 +57,7 @@ func TurnAllHeatersOff( // Set the temp of each hotend. toolheadCount := utils.GetToolheadCount(client) for i := 0; i < toolheadCount; i++ { - var toolTargetRequest = &octoprint.ToolTargetRequest{Targets: map[string]float64{fmt.Sprintf("tool%d", i): 0.0}} + var toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{fmt.Sprintf("tool%d", i): 0.0}} err = toolTargetRequest.Do(client) if err != nil { utils.LogError("TemperaturePresetsPanel.setTemperaturesToPreset()", "Do(ToolTargetRequest)", err) diff --git a/uiWidgets/FanButton.go b/uiWidgets/FanButton.go index 32890020..d5a033a2 100755 --- a/uiWidgets/FanButton.go +++ b/uiWidgets/FanButton.go @@ -4,19 +4,19 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type FanButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client amount int } func CreateFanButton( - client *octoprint.Client, + client *octoprintApis.Client, amount int, ) *FanButton { var ( @@ -47,7 +47,7 @@ func CreateFanButton( } func (this *FanButton) handleClicked() { - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{ fmt.Sprintf("M106 S%d", (255 * this.amount / 100)), } diff --git a/uiWidgets/FilamentExtrudeButton.go b/uiWidgets/FilamentExtrudeButton.go index c3386cec..df434f07 100755 --- a/uiWidgets/FilamentExtrudeButton.go +++ b/uiWidgets/FilamentExtrudeButton.go @@ -2,7 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -10,7 +10,7 @@ type FilamentExtrudeButton struct { *gtk.Button parentWindow *gtk.Window - client *octoprint.Client + client *octoprintApis.Client amountToExtrudeStepButton *AmountToExtrudeStepButton flowRateStepButton *FlowRateStepButton // The flow rate step button is optional. selectToolStepButton *SelectToolStepButton @@ -19,7 +19,7 @@ type FilamentExtrudeButton struct { func CreateFilamentExtrudeButton( parentWindow *gtk.Window, - client *octoprint.Client, + client *octoprintApis.Client, amountToExtrudeStepButton *AmountToExtrudeStepButton, flowRateStepButton *FlowRateStepButton, // The flow rate step button is optional. selectToolStepButton *SelectToolStepButton, @@ -75,7 +75,7 @@ func (this *FilamentExtrudeButton) sendExtrudeCommand(amount int) { return } - cmd := &octoprint.ToolExtrudeRequest{} + cmd := &octoprintApis.ToolExtrudeRequest{} if this.isForward { cmd.Amount = amount } else { diff --git a/uiWidgets/FilamentLoadButton.go b/uiWidgets/FilamentLoadButton.go index caf953b7..47bd1309 100755 --- a/uiWidgets/FilamentLoadButton.go +++ b/uiWidgets/FilamentLoadButton.go @@ -2,7 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -10,14 +10,14 @@ type FilamentLoadButton struct { *gtk.Button parentWindow *gtk.Window - client *octoprint.Client + client *octoprintApis.Client selectToolStepButton *SelectToolStepButton isForward bool } func CreateFilamentLoadButton( parentWindow *gtk.Window, - client *octoprint.Client, + client *octoprintApis.Client, selectToolStepButton *SelectToolStepButton, isForward bool, ) *FilamentLoadButton { @@ -61,7 +61,7 @@ func (this *FilamentLoadButton) sendLoadCommand() { } // BUG: This does not work. At least not on a Prusa i3. Need to get this working with all printers. - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} if this.isForward { cmd.Commands = []string{"G91", "G0 E600 F5000", "G0 E120 F500", "G90"} } else { diff --git a/uiWidgets/FlowRateStepButton.go b/uiWidgets/FlowRateStepButton.go index 85ad50ff..38a07760 100755 --- a/uiWidgets/FlowRateStepButton.go +++ b/uiWidgets/FlowRateStepButton.go @@ -1,17 +1,17 @@ package uiWidgets import ( - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type FlowRateStepButton struct { *StepButton - client *octoprint.Client + client *octoprintApis.Client } func CreateFlowRateStepButton( - client *octoprint.Client, + client *octoprintApis.Client, ) *FlowRateStepButton { base, err := CreateStepButton( 1, @@ -36,7 +36,7 @@ func (this *FlowRateStepButton) Value() int { } func (this *FlowRateStepButton) SendChangeFlowRate() error { - cmd := &octoprint.ToolFlowRateRequest{} + cmd := &octoprintApis.ToolFlowRateRequest{} cmd.Factor = this.Value() utils.Logger.Infof("FlowRateStepButton.SendChangeFlowRate() - changing flow rate to %d%%", cmd.Factor) diff --git a/uiWidgets/HomeAllButton.go b/uiWidgets/HomeAllButton.go index c1c62fe2..e23391d0 100755 --- a/uiWidgets/HomeAllButton.go +++ b/uiWidgets/HomeAllButton.go @@ -2,18 +2,18 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type HomeAllButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client } func CreateHomeAllButton( - client *octoprint.Client, + client *octoprintApis.Client, ) *HomeAllButton { base := utils.MustButtonImageStyle("Home All", "home.svg", "", nil) @@ -33,12 +33,12 @@ func (this *HomeAllButton) handleClicked() { utils.Logger.Infof("Homing the print head") // Version A: - axes := []octoprint.Axis { - octoprint.XAxis, - octoprint.YAxis, - octoprint.ZAxis, + axes := []octoprintApis.Axis { + octoprintApis.XAxis, + octoprintApis.YAxis, + octoprintApis.ZAxis, } - cmd := &octoprint.PrintHeadHomeRequest{Axes: axes} + cmd := &octoprintApis.PrintHeadHomeRequest{Axes: axes} err := cmd.Do(this.client); if err != nil { utils.LogError("HomeAllButton.handleClicked()", "Do(PrintHeadHomeRequest)", err) @@ -47,7 +47,7 @@ func (this *HomeAllButton) handleClicked() { /* // If there are issues with version A, there's also version B: - cmd := &octoprint.CommandRequest{} + cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{ "G28 Z", "G28 X", diff --git a/uiWidgets/HomeButton.go b/uiWidgets/HomeButton.go index b67bee32..2ce45ffe 100755 --- a/uiWidgets/HomeButton.go +++ b/uiWidgets/HomeButton.go @@ -2,22 +2,22 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type HomeButton struct { *gtk.Button - client *octoprint.Client - axes []octoprint.Axis + client *octoprintApis.Client + axes []octoprintApis.Axis } func CreateHomeButton( - client *octoprint.Client, + client *octoprintApis.Client, buttonLabel string, imageFileName string, - axes ...octoprint.Axis, + axes ...octoprintApis.Axis, ) *HomeButton { base := utils.MustButtonImageStyle(buttonLabel, imageFileName, "", nil) @@ -35,7 +35,7 @@ func CreateHomeButton( } func (this *HomeButton) handleClicked() { - cmd := &octoprint.PrintHeadHomeRequest{Axes: this.axes} + cmd := &octoprintApis.PrintHeadHomeRequest{Axes: this.axes} utils.Logger.Infof("Homing the print head in %s axes", this.axes) err := cmd.Do(this.client); if err != nil { diff --git a/uiWidgets/IncreaseZOffsetButton.go b/uiWidgets/IncreaseZOffsetButton.go index 0ec26b2b..0c598e70 100755 --- a/uiWidgets/IncreaseZOffsetButton.go +++ b/uiWidgets/IncreaseZOffsetButton.go @@ -2,7 +2,6 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - // "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/MoveButton.go b/uiWidgets/MoveButton.go index f3675f87..7a5b2dd3 100755 --- a/uiWidgets/MoveButton.go +++ b/uiWidgets/MoveButton.go @@ -2,25 +2,25 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type MoveButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client amountToMoveStepButton *AmountToMoveStepButton - axis octoprint.Axis + axis octoprintApis.Axis direction float64 } func CreateMoveButton( - client *octoprint.Client, + client *octoprintApis.Client, amountToMoveStepButton *AmountToMoveStepButton, label string, image string, - axis octoprint.Axis, + axis octoprintApis.Axis, direction float64, ) *MoveButton { // A little bit of a "chicken or the egg" situation here. Create the @@ -41,15 +41,15 @@ func CreateMoveButton( func (this *MoveButton) handlePressed() { distance := this.amountToMoveStepButton.Value() * this.direction - cmd := &octoprint.PrintHeadJogRequest{} + cmd := &octoprintApis.PrintHeadJogRequest{} switch this.axis { - case octoprint.XAxis: + case octoprintApis.XAxis: cmd.X = distance - case octoprint.YAxis: + case octoprintApis.YAxis: cmd.Y = distance - case octoprint.ZAxis: + case octoprintApis.ZAxis: cmd.Z = distance } diff --git a/uiWidgets/OctoPrintInfoBox.go b/uiWidgets/OctoPrintInfoBox.go index 34ae63d0..6a252a38 100755 --- a/uiWidgets/OctoPrintInfoBox.go +++ b/uiWidgets/OctoPrintInfoBox.go @@ -3,7 +3,7 @@ package uiWidgets import ( "fmt" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,13 +13,13 @@ type OctoPrintInfoBox struct { } func CreateOctoPrintInfoBox( - client *octoprint.Client, + client *octoprintApis.Client, logoWidth int, ) *OctoPrintInfoBox { logoHeight := int(float64(logoWidth) * 1.25) logoImage := utils.MustImageFromFileWithSize("logos/logo-octoprint.png", logoWidth, logoHeight) - versionResponse, err := (&octoprint.VersionRequest{}).Do(client) + versionResponse, err := (&octoprintApis.VersionRequest{}).Do(client) if err != nil { panic(err) } diff --git a/uiWidgets/OctoScreenInfoBox.go b/uiWidgets/OctoScreenInfoBox.go index 4cab3ddb..d502e179 100755 --- a/uiWidgets/OctoScreenInfoBox.go +++ b/uiWidgets/OctoScreenInfoBox.go @@ -4,7 +4,7 @@ import ( // "fmt" "strings" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,7 +13,7 @@ type OctoScreenInfoBox struct { } func CreateOctoScreenInfoBox( - client *octoprint.Client, + client *octoprintApis.Client, octoScreenVersion string, ) *OctoScreenInfoBox { logoImage := utils.MustImageFromFile("logos/octoscreen-isometric-90%.png") diff --git a/uiWidgets/OctoScreenPluginInfoBox.go b/uiWidgets/OctoScreenPluginInfoBox.go index d32060ea..427e4bb9 100755 --- a/uiWidgets/OctoScreenPluginInfoBox.go +++ b/uiWidgets/OctoScreenPluginInfoBox.go @@ -3,7 +3,7 @@ package uiWidgets import ( // "fmt" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -12,7 +12,7 @@ type OctoScreenPluginInfoBox struct { } func CreateOctoScreenPluginInfoBox( - client *octoprint.Client, + client *octoprintApis.Client, octoPrintPluginIsInstalled bool, ) *OctoScreenPluginInfoBox { logoImage := utils.MustImageFromFile("logos/puzzle-piece.png") @@ -20,7 +20,7 @@ func CreateOctoScreenPluginInfoBox( str2 := "" if octoPrintPluginIsInstalled { - getPluginManagerInfoResponse, err := (&octoprint.GetPluginManagerInfoRequest{}).Do(client) + getPluginManagerInfoResponse, err := (&octoprintApis.GetPluginManagerInfoRequest{}).Do(client) if err != nil { panic(err) } diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index 90b8044e..a2833a13 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -14,7 +14,7 @@ type SelectToolStepButton struct { } func CreateSelectToolStepButton( - client *octoprint.Client, + client *octoprintApis.Client, includeBed bool, ) *SelectToolStepButton { toolheadCount := utils.GetToolheadCount(client) diff --git a/uiWidgets/SystemCommandButton.go b/uiWidgets/SystemCommandButton.go index b6218ce4..e29bc071 100755 --- a/uiWidgets/SystemCommandButton.go +++ b/uiWidgets/SystemCommandButton.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,18 +13,18 @@ type SystemCommandButton struct { } func CreateSystemCommandButton( - client *octoprint.Client, + client *octoprintApis.Client, parentWindow *gtk.Window, name string, action string, style string, ) *SystemCommandButton { - systemCommandsResponse, err := (&octoprint.SystemCommandsRequest{}).Do(client) + systemCommandsResponse, err := (&octoprintApis.SystemCommandsRequest{}).Do(client) if err != nil { panic(err) } - var cmd *octoprint.CommandDefinition + var cmd *octoprintApis.CommandDefinition var cb func() for _, commandDefinition := range systemCommandsResponse.Core { @@ -35,8 +35,8 @@ func CreateSystemCommandButton( if cmd != nil { do := func() { - systemExecuteCommandRequest := &octoprint.SystemExecuteCommandRequest{ - Source: octoprint.Core, + systemExecuteCommandRequest := &octoprintApis.SystemExecuteCommandRequest{ + Source: octoprintApis.Core, Action: cmd.Action, } diff --git a/uiWidgets/SystemInfoBox.go b/uiWidgets/SystemInfoBox.go index 86e858be..4a71991c 100755 --- a/uiWidgets/SystemInfoBox.go +++ b/uiWidgets/SystemInfoBox.go @@ -4,7 +4,7 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,7 +13,7 @@ type SystemInfoBox struct { } func CreateSystemInfoBox( - client *octoprint.Client, + client *octoprintApis.Client, image *gtk.Image, str1 string, str2 string, diff --git a/uiWidgets/SystemInformationInfoBox.go b/uiWidgets/SystemInformationInfoBox.go index 4f9e719f..60687aa6 100755 --- a/uiWidgets/SystemInformationInfoBox.go +++ b/uiWidgets/SystemInformationInfoBox.go @@ -7,8 +7,6 @@ import ( "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" - // "github.com/mcuadros/go-octoprint" - // "github.com/shirou/gopsutil/load" "github.com/shirou/gopsutil/mem" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go index 6a7d7175..05e346a1 100755 --- a/uiWidgets/TemperatureIncreaseButton.go +++ b/uiWidgets/TemperatureIncreaseButton.go @@ -2,21 +2,21 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type TemperatureIncreaseButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client temperatureAmountStepButton *TemperatureAmountStepButton selectToolStepButton *SelectToolStepButton isIncrease bool } func CreateTemperatureIncreaseButton( - client *octoprint.Client, + client *octoprintApis.Client, temperatureAmountStepButton *TemperatureAmountStepButton, selectToolStepButton *SelectToolStepButton, isIncrease bool, diff --git a/uiWidgets/TemperaturePresetButton.go b/uiWidgets/TemperaturePresetButton.go index ebf11891..26ffbd47 100755 --- a/uiWidgets/TemperaturePresetButton.go +++ b/uiWidgets/TemperaturePresetButton.go @@ -2,25 +2,25 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) type TemperaturePresetButton struct { *gtk.Button - client *octoprint.Client + client *octoprintApis.Client selectToolStepButton *SelectToolStepButton imageFileName string - temperaturePreset *octoprint.TemperaturePreset + temperaturePreset *octoprintApis.TemperaturePreset callback func() } func CreateTemperaturePresetButton( - client *octoprint.Client, + client *octoprintApis.Client, selectToolStepButton *SelectToolStepButton, imageFileName string, - temperaturePreset *octoprint.TemperaturePreset, + temperaturePreset *octoprintApis.TemperaturePreset, callback func(), ) *TemperaturePresetButton { presetName := utils.StrEllipsisLen(temperaturePreset.Name, 10) @@ -66,7 +66,7 @@ func (this *TemperaturePresetButton) handleClicked() { */ // Set the bed's temp. - bedTargetRequest := &octoprint.BedTargetRequest{Target: this.temperaturePreset.Bed} + bedTargetRequest := &octoprintApis.BedTargetRequest{Target: this.temperaturePreset.Bed} err := bedTargetRequest.Do(this.client) if err != nil { utils.LogError("TemperaturePresetButton.handleClicked()", "Do(BedTargetRequest)", err) @@ -74,12 +74,12 @@ func (this *TemperaturePresetButton) handleClicked() { } // Set the hotend's temp. - var toolTargetRequest *octoprint.ToolTargetRequest + var toolTargetRequest *octoprintApis.ToolTargetRequest if currentTool == "bed" { // If current tool is set to "bed", use tool0. - toolTargetRequest = &octoprint.ToolTargetRequest{Targets: map[string]float64{"tool0": this.temperaturePreset.Extruder}} + toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{"tool0": this.temperaturePreset.Extruder}} } else { - toolTargetRequest = &octoprint.ToolTargetRequest{Targets: map[string]float64{currentTool: this.temperaturePreset.Extruder}} + toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{currentTool: this.temperaturePreset.Extruder}} } err = toolTargetRequest.Do(this.client) diff --git a/uiWidgets/TemperatureStatusBox.go b/uiWidgets/TemperatureStatusBox.go index 6cd3e18b..b655ec8e 100755 --- a/uiWidgets/TemperatureStatusBox.go +++ b/uiWidgets/TemperatureStatusBox.go @@ -4,8 +4,8 @@ import ( // "time" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,12 +13,12 @@ type TemperatureStatusBox struct { *gtk.Box interfaces.ITemperatureDataDisplay - client *octoprint.Client + client *octoprintApis.Client labelWithImages map[string]*utils.LabelWithImage } func CreateTemperatureStatusBox( - client *octoprint.Client, + client *octoprintApis.Client, includeHotends bool, includeBed bool, ) *TemperatureStatusBox { @@ -44,7 +44,7 @@ func CreateTemperatureStatusBox( instance.SetVAlign(gtk.ALIGN_CENTER) instance.SetHAlign(gtk.ALIGN_CENTER) - var bedTemperatureData *octoprint.TemperatureData = nil + var bedTemperatureData *octoprintApis.TemperatureData = nil var hotendIndex int = 0 var hotendCount int = utils.GetToolheadCount(client) for key, temperatureData := range currentTemperatureData { @@ -80,7 +80,7 @@ func CreateTemperatureStatusBox( } // interfaces.ITemperatureDataDisplay -func (this *TemperatureStatusBox) UpdateTemperatureData(currentTemperatureData map[string]octoprint.TemperatureData) { +func (this *TemperatureStatusBox) UpdateTemperatureData(currentTemperatureData map[string]octoprintApis.TemperatureData) { for key, temperatureData := range currentTemperatureData { if labelWithImage, ok := this.labelWithImages[key]; ok { temperatureDataString := utils.GetTemperatureDataString(temperatureData) diff --git a/uiWidgets/ToolButton.go b/uiWidgets/ToolButton.go index da3b3e7e..2320e6e2 100755 --- a/uiWidgets/ToolButton.go +++ b/uiWidgets/ToolButton.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -43,12 +43,12 @@ type ToolButton struct { isHeating bool tool string - printer *octoprint.Client + printer *octoprintApis.Client } func CreateToolButton( index int, - printer *octoprint.Client, + printer *octoprintApis.Client, ) *ToolButton { imageFileName := ToolImageFileName(index) toolName := ToolName(index) @@ -78,7 +78,7 @@ func (this *ToolButton) UpdateStatus(heating bool) { this.isHeating = heating } -func (this *ToolButton) SetTemperatures(temperatureData octoprint.TemperatureData) { +func (this *ToolButton) SetTemperatures(temperatureData octoprintApis.TemperatureData) { text := utils.GetTemperatureDataString(temperatureData) this.SetLabel(text) this.UpdateStatus(temperatureData.Target > 0) @@ -87,7 +87,7 @@ func (this *ToolButton) SetTemperatures(temperatureData octoprint.TemperatureDat func (this *ToolButton) GetProfileTemperature() float64 { temperature := 0.0 - settingsResponse, err := (&octoprint.SettingsRequest{}).Do(this.printer) + settingsResponse, err := (&octoprintApis.SettingsRequest{}).Do(this.printer) if err != nil { utils.LogError("ToolButton.GetProfileTemperature()", "Do(SettingsRequest)", err) return 0 @@ -127,13 +127,13 @@ func (this *ToolButton) clicked() { } if this.tool == "bed" { - cmd := &octoprint.BedTargetRequest{Target: target} + cmd := &octoprintApis.BedTargetRequest{Target: target} err = cmd.Do(this.printer) if err != nil { utils.LogError("ToolButton.clicked()", "Do(BedTargetRequest)", err) } } else { - cmd := &octoprint.ToolTargetRequest{Targets: map[string]float64{this.tool: target}} + cmd := &octoprintApis.ToolTargetRequest{Targets: map[string]float64{this.tool: target}} err = cmd.Do(this.printer) if err != nil { utils.LogError("ToolButton.clicked()", "Do(ToolTargetRequest)", err) diff --git a/uiWidgets/ToolPrintingButon.go b/uiWidgets/ToolPrintingButon.go index 8133e8ef..662d1d1d 100755 --- a/uiWidgets/ToolPrintingButon.go +++ b/uiWidgets/ToolPrintingButon.go @@ -2,7 +2,6 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" - // "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/utils/FileResponsesSortedByDate.go b/utils/FileResponsesSortedByDate.go index 8f7b69ef..0ded5105 100755 --- a/utils/FileResponsesSortedByDate.go +++ b/utils/FileResponsesSortedByDate.go @@ -4,12 +4,10 @@ import ( // "fmt" // "sort" - "github.com/mcuadros/go-octoprint" - // "github.com/mcuadros/go-octoprint/apis" - // "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) -type FileResponsesSortedByDate []*octoprint.FileResponse +type FileResponsesSortedByDate []*octoprintApis.FileResponse func (this FileResponsesSortedByDate) Len() int { return len(this) diff --git a/utils/FileResponsesSortedByName.go b/utils/FileResponsesSortedByName.go index 9fbd6dd1..f9ceca5f 100755 --- a/utils/FileResponsesSortedByName.go +++ b/utils/FileResponsesSortedByName.go @@ -5,12 +5,10 @@ import ( // "sort" // "strings" - "github.com/mcuadros/go-octoprint" - // "github.com/mcuadros/go-octoprint/apis" - // "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) -type FileResponsesSortedByName []*octoprint.FileResponse +type FileResponsesSortedByName []*octoprintApis.FileResponse func (this FileResponsesSortedByName) Len() int { return len(this) diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go index d2cc0fc4..89ec0520 100755 --- a/utils/LocationHistory.go +++ b/utils/LocationHistory.go @@ -4,20 +4,18 @@ import ( // "fmt" // "sort" - "github.com/mcuadros/go-octoprint" - // "github.com/mcuadros/go-octoprint/apis" - // "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) type LocationHistory struct { - Locations []octoprint.Location + Locations []octoprintApis.Location } func (this *LocationHistory) Length() int { return len(this.Locations) } -func (this *LocationHistory) CurrentLocation() octoprint.Location { +func (this *LocationHistory) CurrentLocation() octoprintApis.Location { length := this.Length() if length < 1 { panic("LocationHistory.current() - locations is empty") @@ -28,7 +26,7 @@ func (this *LocationHistory) CurrentLocation() octoprint.Location { func (this *LocationHistory) GoForward(folder string) { newLocation := string(this.CurrentLocation()) + "/" + folder - this.Locations = append(this.Locations, octoprint.Location(newLocation)) + this.Locations = append(this.Locations, octoprintApis.Location(newLocation)) } func (this *LocationHistory) GoBack() { diff --git a/utils/UpdateTemperaturesBackgroundTask.go b/utils/UpdateTemperaturesBackgroundTask.go index e5ad09ca..02e203ab 100755 --- a/utils/UpdateTemperaturesBackgroundTask.go +++ b/utils/UpdateTemperaturesBackgroundTask.go @@ -3,17 +3,17 @@ package utils import ( "time" - "github.com/mcuadros/go-octoprint" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) // TODO: convert this into a singleton class var UpdateTemperaturesBackgroundTask *BackgroundTask = nil var temperatureDataDisplays []interfaces.ITemperatureDataDisplay -var registeredClient *octoprint.Client = nil +var registeredClient *octoprintApis.Client = nil -func CreateUpdateTemperaturesBackgroundTask(temperatureDataDisplay interfaces.ITemperatureDataDisplay, client *octoprint.Client) { +func CreateUpdateTemperaturesBackgroundTask(temperatureDataDisplay interfaces.ITemperatureDataDisplay, client *octoprintApis.Client) { if UpdateTemperaturesBackgroundTask != nil { Logger.Error("UpdateTemperaturesBackgroundTask.CreateUpdateTemperaturesBackgroundTask() - updateTemperaturesBackgroundTask has already been set") return @@ -24,7 +24,7 @@ func CreateUpdateTemperaturesBackgroundTask(temperatureDataDisplay interfaces.IT UpdateTemperaturesBackgroundTask.Start() } -func RegisterTemperatureStatusBox(temperatureDataDisplay interfaces.ITemperatureDataDisplay, client *octoprint.Client) { +func RegisterTemperatureStatusBox(temperatureDataDisplay interfaces.ITemperatureDataDisplay, client *octoprintApis.Client) { temperatureDataDisplays = append(temperatureDataDisplays, temperatureDataDisplay) registeredClient = client } diff --git a/utils/tools.go b/utils/tools.go index dab1ae55..f702c6a3 100755 --- a/utils/tools.go +++ b/utils/tools.go @@ -6,23 +6,23 @@ import ( "strconv" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) var cachedToolheadCount = -1 -func GetToolheadCount(client *octoprint.Client) int { +func GetToolheadCount(client *octoprintApis.Client) int { if cachedToolheadCount != -1 { return cachedToolheadCount } - connectionResponse, err := (&octoprint.ConnectionRequest{}).Do(client) + connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(client) if err != nil { LogError("toolhaad.GetToolheadCount()", "Do(ConnectionRequest)", err) return 0 } - printerProfile, err := (&octoprint.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(client) + printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(client) if err != nil { LogError("toolhaad.GetToolheadCount()", "Do(PrinterProfilesRequest)", err) return 0 @@ -72,11 +72,11 @@ func GetDisplayNameForTool(toolName string) string { } -func GetToolTarget(client *octoprint.Client, tool string) (float64, error) { +func GetToolTarget(client *octoprintApis.Client, tool string) (float64, error) { Logger.Debug("entering Tools.GetToolTarget()") - fullStateRequest, err := (&octoprint.FullStateRequest{ + fullStateRequest, err := (&octoprintApis.FullStateRequest{ Exclude: []string{"sd", "state"}, }).Do(client) @@ -98,27 +98,27 @@ func GetToolTarget(client *octoprint.Client, tool string) (float64, error) { } -func SetToolTarget(client *octoprint.Client, tool string, target float64) error { +func SetToolTarget(client *octoprintApis.Client, tool string, target float64) error { Logger.Debug("entering Tools.SetToolTarget()") if tool == "bed" { - cmd := &octoprint.BedTargetRequest{Target: target} + cmd := &octoprintApis.BedTargetRequest{Target: target} Logger.Debug("leaving Tools.SetToolTarget()") return cmd.Do(client) } - cmd := &octoprint.ToolTargetRequest{Targets: map[string]float64{tool: target}} + cmd := &octoprintApis.ToolTargetRequest{Targets: map[string]float64{tool: target}} Logger.Debug("leaving Tools.SetToolTarget()") return cmd.Do(client) } -func GetCurrentTemperatureData(client *octoprint.Client) (map[string]octoprint.TemperatureData, error) { +func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]octoprintApis.TemperatureData, error) { Logger.Debug("entering Tools.GetCurrentTemperatureData()") - temperatureDataResponse, err := (&octoprint.TemperatureDataRequest{}).Do(client) + temperatureDataResponse, err := (&octoprintApis.TemperatureDataRequest{}).Do(client) if err != nil { LogError("tools.GetCurrentTemperatureData()", "Do(TemperatureDataRequest)", err) @@ -147,7 +147,7 @@ func GetCurrentTemperatureData(client *octoprint.Client) (map[string]octoprint.T } -func CurrentHotendTemperatureIsTooLow(client *octoprint.Client, extruderId, action string, parentWindow *gtk.Window) bool { +func CurrentHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, action string, parentWindow *gtk.Window) bool { currentTemperatureData, err := GetCurrentTemperatureData(client) if err != nil { LogError("tools.CurrentHotendTemperatureIsTooLow()", "GetCurrentTemperatureData()", err) @@ -198,6 +198,6 @@ func GetNozzleFileName(hotendIndex, hotendCount int) string { return strImageFileName } -func GetTemperatureDataString(temperatureData octoprint.TemperatureData) string { +func GetTemperatureDataString(temperatureData octoprintApis.TemperatureData) string { return fmt.Sprintf("%.0f°C / %.0f°C", temperatureData.Actual, temperatureData.Target) } \ No newline at end of file diff --git a/utils/ui_utils.go b/utils/ui_utils.go index 0f922286..1c13736b 100755 --- a/utils/ui_utils.go +++ b/utils/ui_utils.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/mcuadros/go-octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis" ) @@ -144,7 +144,7 @@ func messageDialogBox(parentWindow *gtk.Window, messageType gtk.MessageType, mes dialogBox.Run() } -func HotendTemperatureIsTooLow(temperatureData octoprint.TemperatureData, action string, parentWindow *gtk.Window) bool { +func HotendTemperatureIsTooLow(temperatureData octoprintApis.TemperatureData, action string, parentWindow *gtk.Window) bool { targetTemperature := temperatureData.Target Logger.Infof("filament.hotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) From 87823da6b10cd14aa2c67cf8b52fbedcfa20c3a0 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 31 Jan 2021 14:04:29 -0800 Subject: [PATCH 26/94] Hard fork of mcuadros/go-octoprint-moved to octoprintApis and octoprintApis/dataModels --- octoprintApis/BedOffsetRequest.go | 40 + octoprintApis/BedStateRequest.go | 44 + octoprintApis/BedTargetRequest.go | 40 + octoprintApis/CancelRequest.go | 27 + octoprintApis/CommandRequest.go | 32 + octoprintApis/ConnectRequest.go | 56 + octoprintApis/ConnectionRequest.go | 30 + octoprintApis/CustomCommandsRequest.go | 31 + octoprintApis/DeleteFileRequest.go | 29 + octoprintApis/DisconnectRequest.go | 26 + octoprintApis/FakesAckRequest.go | 31 + octoprintApis/FileRequest.go | 100 +- octoprintApis/FilesRequest.go | 47 + octoprintApis/FullStateRequest.go | 30 +- octoprintApis/JobRequest.go | 28 +- octoprintApis/LICENSE | 0 octoprintApis/NotificationRequest.go | 30 + octoprintApis/OctoScreenSettingsRequest.go | 28 + octoprintApis/PauseRequest.go | 41 + octoprintApis/PluginManagerInfoRequest.go | 42 + octoprintApis/PrintHeadHomeRequest.go | 40 + octoprintApis/PrintHeadJogRequest.go | 60 + octoprintApis/PrinterProfilesRequest.go | 9 +- octoprintApis/README.md | 0 octoprintApis/RestartRequest.go | 29 + octoprintApis/RunZOffsetCalibrationRequest.go | 26 + octoprintApis/SdInitRequest.go | 23 + octoprintApis/SdRefreshRequest.go | 21 + octoprintApis/SdReleaseRequest.go | 23 + octoprintApis/SdStateRequest.go | 32 + octoprintApis/SelectFileRequest.go | 10 +- octoprintApis/StartRequest.go | 27 + octoprintApis/StatusMapping.go | 24 + octoprintApis/TemperatureDataRequest.go | 67 ++ octoprintApis/ToolExtrudeRequest.go | 42 + octoprintApis/ToolFlowRateRequest.go | 40 + octoprintApis/ToolOffsetRequest.go | 41 + octoprintApis/ToolSelectRequest.go | 41 + octoprintApis/ToolStateRequest.go | 61 + octoprintApis/ToolTargetRequest.go | 41 + octoprintApis/UploadFileRequest.go | 92 ++ octoprintApis/ZOffsetRequest.go | 64 + octoprintApis/_examples/state/main.go | 12 +- octoprintApis/client.go | 186 +-- octoprintApis/common.go | 1026 ----------------- octoprintApis/common_test.go | 6 +- octoprintApis/connection.go | 111 +- octoprintApis/dataModels/ApiConfig.go | 11 + octoprintApis/dataModels/Axis.go | 10 + octoprintApis/dataModels/CommandDefinition.go | 38 + octoprintApis/dataModels/CommandSource.go | 13 + .../dataModels/ConnectionResponse.go | 43 + octoprintApis/dataModels/ConnectionState.go | 45 + octoprintApis/dataModels/ControlContainer.go | 23 + octoprintApis/dataModels/ControlDefinition.go | 79 ++ octoprintApis/dataModels/ControlInput.go | 29 + .../dataModels/CustomCommandsResponse.go | 7 + octoprintApis/dataModels/FeaturesConfig.go | 86 ++ octoprintApis/dataModels/Filament.go | 10 + octoprintApis/dataModels/FileResponse.go | 90 ++ octoprintApis/dataModels/FilesResponse.go | 16 + octoprintApis/dataModels/FolderConfig.go | 29 + octoprintApis/dataModels/FullStateResponse.go | 13 + .../dataModels/GCodeAnalysisInformation.go | 10 + .../dataModels/HistoricTemperatureData.go | 38 + .../{ => dataModels}/JobInformation.go | 3 +- octoprintApis/dataModels/JobResponse.go | 19 + octoprintApis/dataModels/JsonTime.go | 29 + octoprintApis/dataModels/Location.go | 10 + octoprintApis/dataModels/MenuItem.go | 9 + .../dataModels/NotificationResponse.go | 7 + .../dataModels/OctoScreenSettingsResponse.go | 16 + octoprintApis/dataModels/PauseAction.go | 15 + octoprintApis/dataModels/Plugin.go | 28 + .../dataModels/PluginManagerInfoResponse.go | 12 + octoprintApis/dataModels/PrintStats.go | 20 + .../dataModels/PrinterProfileResponse.go | 20 + .../dataModels/PrinterProfilesResponse.go | 6 + octoprintApis/dataModels/PrinterState.go | 16 + octoprintApis/dataModels/Profile.go | 10 + .../{ => dataModels}/ProgressInformation.go | 3 +- octoprintApis/dataModels/Reference.go | 16 + octoprintApis/dataModels/SdState.go | 7 + octoprintApis/dataModels/SerialConfig.go | 102 ++ octoprintApis/dataModels/ServerConfig.go | 58 + octoprintApis/dataModels/SettingsResponse.go | 35 + .../dataModels/SystemCommandsResponse.go | 8 + octoprintApis/dataModels/TemperatureConfig.go | 21 + .../{ => dataModels}/TemperatureData.go | 3 +- .../dataModels/TemperatureDataResponse.go | 13 + octoprintApis/dataModels/TemperaturePreset.go | 9 + .../TemperatureStateResponse.go | 4 +- octoprintApis/dataModels/TerminalFilter.go | 9 + .../dataModels/UploadFileResponse.go | 25 + octoprintApis/dataModels/VersionResponse.go | 12 + octoprintApis/dataModels/WebcamConfig.go | 41 + octoprintApis/dataModels/ZOffsetResponse.go | 7 + octoprintApis/files.go | 239 +--- octoprintApis/files_test.go | 2 + octoprintApis/job.go | 174 +-- octoprintApis/plugin_manager.go | 76 -- octoprintApis/printer.go | 671 +---------- octoprintApis/printer_test.go | 9 +- octoprintApis/settings.go | 16 +- octoprintApis/settings_test.go | 2 + octoprintApis/system.go | 25 +- octoprintApis/system_test.go | 2 + octoprintApis/version.go | 12 +- octoprintApis/zbolt.go | 148 +-- 109 files changed, 2746 insertions(+), 2699 deletions(-) create mode 100755 octoprintApis/BedOffsetRequest.go create mode 100755 octoprintApis/BedStateRequest.go create mode 100755 octoprintApis/BedTargetRequest.go create mode 100755 octoprintApis/CancelRequest.go create mode 100755 octoprintApis/CommandRequest.go create mode 100755 octoprintApis/ConnectRequest.go create mode 100755 octoprintApis/ConnectionRequest.go create mode 100755 octoprintApis/CustomCommandsRequest.go create mode 100755 octoprintApis/DeleteFileRequest.go create mode 100755 octoprintApis/DisconnectRequest.go create mode 100755 octoprintApis/FakesAckRequest.go create mode 100755 octoprintApis/FilesRequest.go mode change 100644 => 100755 octoprintApis/LICENSE create mode 100755 octoprintApis/NotificationRequest.go create mode 100755 octoprintApis/OctoScreenSettingsRequest.go create mode 100755 octoprintApis/PauseRequest.go create mode 100755 octoprintApis/PluginManagerInfoRequest.go create mode 100755 octoprintApis/PrintHeadHomeRequest.go create mode 100755 octoprintApis/PrintHeadJogRequest.go mode change 100644 => 100755 octoprintApis/PrinterProfilesRequest.go mode change 100644 => 100755 octoprintApis/README.md create mode 100755 octoprintApis/RestartRequest.go create mode 100755 octoprintApis/RunZOffsetCalibrationRequest.go create mode 100755 octoprintApis/SdInitRequest.go create mode 100755 octoprintApis/SdRefreshRequest.go create mode 100755 octoprintApis/SdReleaseRequest.go create mode 100755 octoprintApis/SdStateRequest.go create mode 100755 octoprintApis/StartRequest.go create mode 100755 octoprintApis/StatusMapping.go create mode 100755 octoprintApis/TemperatureDataRequest.go create mode 100755 octoprintApis/ToolExtrudeRequest.go create mode 100755 octoprintApis/ToolFlowRateRequest.go create mode 100755 octoprintApis/ToolOffsetRequest.go create mode 100755 octoprintApis/ToolSelectRequest.go create mode 100755 octoprintApis/ToolStateRequest.go create mode 100755 octoprintApis/ToolTargetRequest.go create mode 100755 octoprintApis/UploadFileRequest.go create mode 100755 octoprintApis/ZOffsetRequest.go mode change 100644 => 100755 octoprintApis/_examples/state/main.go mode change 100644 => 100755 octoprintApis/common_test.go create mode 100755 octoprintApis/dataModels/ApiConfig.go create mode 100755 octoprintApis/dataModels/Axis.go create mode 100755 octoprintApis/dataModels/CommandDefinition.go create mode 100755 octoprintApis/dataModels/CommandSource.go create mode 100755 octoprintApis/dataModels/ConnectionResponse.go create mode 100755 octoprintApis/dataModels/ConnectionState.go create mode 100755 octoprintApis/dataModels/ControlContainer.go create mode 100755 octoprintApis/dataModels/ControlDefinition.go create mode 100755 octoprintApis/dataModels/ControlInput.go create mode 100755 octoprintApis/dataModels/CustomCommandsResponse.go create mode 100755 octoprintApis/dataModels/FeaturesConfig.go create mode 100755 octoprintApis/dataModels/Filament.go create mode 100755 octoprintApis/dataModels/FileResponse.go create mode 100755 octoprintApis/dataModels/FilesResponse.go create mode 100755 octoprintApis/dataModels/FolderConfig.go create mode 100755 octoprintApis/dataModels/FullStateResponse.go create mode 100755 octoprintApis/dataModels/GCodeAnalysisInformation.go create mode 100755 octoprintApis/dataModels/HistoricTemperatureData.go rename octoprintApis/{ => dataModels}/JobInformation.go (97%) create mode 100755 octoprintApis/dataModels/JobResponse.go create mode 100755 octoprintApis/dataModels/JsonTime.go create mode 100755 octoprintApis/dataModels/Location.go create mode 100755 octoprintApis/dataModels/MenuItem.go create mode 100755 octoprintApis/dataModels/NotificationResponse.go create mode 100755 octoprintApis/dataModels/OctoScreenSettingsResponse.go create mode 100755 octoprintApis/dataModels/PauseAction.go create mode 100755 octoprintApis/dataModels/Plugin.go create mode 100755 octoprintApis/dataModels/PluginManagerInfoResponse.go create mode 100755 octoprintApis/dataModels/PrintStats.go create mode 100755 octoprintApis/dataModels/PrinterProfileResponse.go create mode 100755 octoprintApis/dataModels/PrinterProfilesResponse.go create mode 100755 octoprintApis/dataModels/PrinterState.go create mode 100755 octoprintApis/dataModels/Profile.go rename octoprintApis/{ => dataModels}/ProgressInformation.go (97%) create mode 100755 octoprintApis/dataModels/Reference.go create mode 100755 octoprintApis/dataModels/SdState.go create mode 100755 octoprintApis/dataModels/SerialConfig.go create mode 100755 octoprintApis/dataModels/ServerConfig.go create mode 100755 octoprintApis/dataModels/SettingsResponse.go create mode 100755 octoprintApis/dataModels/SystemCommandsResponse.go create mode 100755 octoprintApis/dataModels/TemperatureConfig.go rename octoprintApis/{ => dataModels}/TemperatureData.go (95%) create mode 100755 octoprintApis/dataModels/TemperatureDataResponse.go create mode 100755 octoprintApis/dataModels/TemperaturePreset.go rename octoprintApis/{ => dataModels}/TemperatureStateResponse.go (97%) create mode 100755 octoprintApis/dataModels/TerminalFilter.go create mode 100755 octoprintApis/dataModels/UploadFileResponse.go create mode 100755 octoprintApis/dataModels/VersionResponse.go create mode 100755 octoprintApis/dataModels/WebcamConfig.go create mode 100755 octoprintApis/dataModels/ZOffsetResponse.go mode change 100644 => 100755 octoprintApis/files_test.go delete mode 100755 octoprintApis/plugin_manager.go mode change 100644 => 100755 octoprintApis/settings_test.go mode change 100644 => 100755 octoprintApis/system_test.go mode change 100644 => 100755 octoprintApis/version.go diff --git a/octoprintApis/BedOffsetRequest.go b/octoprintApis/BedOffsetRequest.go new file mode 100755 index 00000000..5ec87bb7 --- /dev/null +++ b/octoprintApis/BedOffsetRequest.go @@ -0,0 +1,40 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// BedOffsetRequest sets the given temperature offset on the printer’s bed. +type BedOffsetRequest struct { + // Offset is offset to set. + Offset int `json:"offset"` +} + +// Do sends an API request and returns an error if any. +func (cmd *BedOffsetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *BedOffsetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + BedOffsetRequest + }{ + Command: "offset", + BedOffsetRequest: *cmd, + }) +} diff --git a/octoprintApis/BedStateRequest.go b/octoprintApis/BedStateRequest.go new file mode 100755 index 00000000..3b1a1abd --- /dev/null +++ b/octoprintApis/BedStateRequest.go @@ -0,0 +1,44 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// BedStateRequest retrieves the current temperature data (actual, target and +// offset) plus optionally a (limited) history (actual, target, timestamp) for +// the printer’s heated bed. +// +// It’s also possible to retrieve the temperature history by supplying the +// history query parameter set to true. The amount of returned history data +// points can be limited using the limit query parameter. +type BedStateRequest struct { + // History if true retrieve the temperature history. + IncludeHistory bool + + // Limit limtis amount of returned history data points. + Limit int +} + +// Do sends an API request and returns the API response. +func (cmd *BedStateRequest) Do(c *Client) (*dataModels.TemperatureStateResponse, error) { + uri := fmt.Sprintf("%s?history=%t&limit=%d", PrinterBedApiUri, cmd.IncludeHistory, cmd.Limit) + b, err := c.doJsonRequest("GET", uri, nil, PrintBedErrors) + if err != nil { + return nil, err + } + + r := &dataModels.TemperatureStateResponse{} + if err := json.Unmarshal(b, &r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/BedTargetRequest.go b/octoprintApis/BedTargetRequest.go new file mode 100755 index 00000000..536bd7b7 --- /dev/null +++ b/octoprintApis/BedTargetRequest.go @@ -0,0 +1,40 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// BedTargetRequest sets the given target temperature on the printer’s bed. +type BedTargetRequest struct { + // Target temperature to set. + Target float64 `json:"target"` +} + +// Do sends an API request and returns an error if any. +func (cmd *BedTargetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterBedApiUri, b, PrintBedErrors) + return err +} + +func (cmd *BedTargetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + BedTargetRequest + }{ + Command: "target", + BedTargetRequest: *cmd, + }) +} diff --git a/octoprintApis/CancelRequest.go b/octoprintApis/CancelRequest.go new file mode 100755 index 00000000..33c69cff --- /dev/null +++ b/octoprintApis/CancelRequest.go @@ -0,0 +1,27 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "io" + // "log" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// CancelRequest cancels the current print job. +type CancelRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *CancelRequest) Do(c *Client) error { + payload := map[string]string{"command": "cancel"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", JobApiUri, buffer, JobToolErrors) + return err +} diff --git a/octoprintApis/CommandRequest.go b/octoprintApis/CommandRequest.go new file mode 100755 index 00000000..f2dbaa84 --- /dev/null +++ b/octoprintApis/CommandRequest.go @@ -0,0 +1,32 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// CommandRequest sends any command to the printer via the serial interface. +// Should be used with some care as some commands can interfere with or even +// stop a running print job. +type CommandRequest struct { + // Commands list of commands to send to the printer. + Commands []string `json:"commands"` +} + +// Do sends an API request and returns an error if any. +func (cmd *CommandRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterCommandApiUri, b, nil) + return err +} diff --git a/octoprintApis/ConnectRequest.go b/octoprintApis/ConnectRequest.go new file mode 100755 index 00000000..a74ded5d --- /dev/null +++ b/octoprintApis/ConnectRequest.go @@ -0,0 +1,56 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "io" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ConnectRequest sets the given target temperature on the printer’s tools. +type ConnectRequest struct { + // Port specific port to connect to. If not set the current `portPreference` + // will be used, or if no preference is available auto detection will be + // attempted. + Port string `json:"port,omitempty"` + + // BaudRate specific baudrate to connect with. If not set the current + // `baudratePreference` will be used, or if no preference is available auto + // detection will be attempted. + BaudRate int `json:"baudrate,omitempty"` + + // PrinterProfile specific printer profile to use for connection. If not set + // the current default printer profile will be used. + PrinterProfile string `json:"printerProfile,omitempty"` + + // Save whether to save the request’s port and baudrate settings as new + // preferences. + Save bool `json:"save"` + + // Autoconnect whether to automatically connect to the printer on + // OctoPrint’s startup in the future. + Autoconnect bool `json:"autoconnect"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ConnectRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + return err +} + +func (cmd *ConnectRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ConnectRequest + }{ + Command: "connect", + ConnectRequest: *cmd, + }) +} diff --git a/octoprintApis/ConnectionRequest.go b/octoprintApis/ConnectionRequest.go new file mode 100755 index 00000000..a4a051ee --- /dev/null +++ b/octoprintApis/ConnectionRequest.go @@ -0,0 +1,30 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + // "io" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ConnectionRequest Retrieve the current connection settings, including +// information regarding the available baudrates and serial ports and the +// current connection state. +type ConnectionRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *ConnectionRequest) Do(c *Client) (*dataModels.ConnectionResponse, error) { + b, err := c.doJsonRequest("GET", ConnectionApiUri, nil, nil) + if err != nil { + return nil, err + } + + r := &dataModels.ConnectionResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/CustomCommandsRequest.go b/octoprintApis/CustomCommandsRequest.go new file mode 100755 index 00000000..5a7e9162 --- /dev/null +++ b/octoprintApis/CustomCommandsRequest.go @@ -0,0 +1,31 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// CustomCommandsRequest retrieves all configured system controls. +type CustomCommandsRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *CustomCommandsRequest) Do(c *Client) (*dataModels.CustomCommandsResponse, error) { + b, err := c.doJsonRequest("GET", PrinterCommandCustomApiUri, nil, nil) + if err != nil { + return nil, err + } + + r := &dataModels.CustomCommandsResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/DeleteFileRequest.go b/octoprintApis/DeleteFileRequest.go new file mode 100755 index 00000000..0f033dc2 --- /dev/null +++ b/octoprintApis/DeleteFileRequest.go @@ -0,0 +1,29 @@ +package octoprintApis + +import ( + "fmt" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// DeleteFileRequest delete the selected path on the selected location. +type DeleteFileRequest struct { + // Location is the target location on which to delete the file, either + // `local` (for OctoPrint’s uploads folder) or \sdcard\ for the printer’s + // SD card (if available) + Location dataModels.Location + + // Path of the file to delete + Path string +} + +// Do sends an API request and returns error if any. +func (req *DeleteFileRequest) Do(c *Client) error { + uri := fmt.Sprintf("%s/%s/%s", FilesApiUri, req.Location, req.Path) + if _, err := c.doJsonRequest("DELETE", uri, nil, FilesLocationDeleteErrors); err != nil { + return err + } + + return nil +} diff --git a/octoprintApis/DisconnectRequest.go b/octoprintApis/DisconnectRequest.go new file mode 100755 index 00000000..416c6679 --- /dev/null +++ b/octoprintApis/DisconnectRequest.go @@ -0,0 +1,26 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "io" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// DisconnectRequest instructs OctoPrint to disconnect from the printer. +type DisconnectRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *DisconnectRequest) Do(c *Client) error { + payload := map[string]string{"command": "disconnect"} + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(payload); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + return err +} diff --git a/octoprintApis/FakesAckRequest.go b/octoprintApis/FakesAckRequest.go new file mode 100755 index 00000000..3b937685 --- /dev/null +++ b/octoprintApis/FakesAckRequest.go @@ -0,0 +1,31 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "io" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// FakesAckRequest fakes an acknowledgment message for OctoPrint in case one got +// lost on the serial line and the communication with the printer since stalled. +// +// This should only be used in “emergencies” (e.g. to save prints), the reason +// for the lost acknowledgment should always be properly investigated and +// removed instead of depending on this “symptom solver”. +type FakesAckRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *FakesAckRequest) Do(c *Client) error { + payload := map[string]string{"command": "fake_ack"} + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(payload); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + return err +} diff --git a/octoprintApis/FileRequest.go b/octoprintApis/FileRequest.go index f87ba776..d337b28f 100755 --- a/octoprintApis/FileRequest.go +++ b/octoprintApis/FileRequest.go @@ -1,27 +1,27 @@ +//package apis package octoprintApis import ( - "fmt" "encoding/json" - + "fmt" // "log" // "strconv" // "strings" // "time" - // "../octoprint" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + // Retrieve a specific file’s or folder’s information // GET /api/files/(string:location)/(path:filename) // https://docs.octoprint.org/en/master/api/files.html#retrieve-a-specific-file-s-or-folder-s-information - // FileRequest retrieves the selected file’s or folder’s information. type FileRequest struct { // Location of the file for which to retrieve the information/ Can be either // `local` or `sdcard`. - Location Location + Location dataModels.Location // Filename of the file for which to retrieve the information. Filename string @@ -31,103 +31,21 @@ type FileRequest struct { Recursive bool } -// FileResponse contains information regarding a file. -// https://docs.octoprint.org/en/master/api/datamodel.html#file-information -type FileResponse struct { - // Name is name of the file without path. E.g. “file.gco” for a file - // “file.gco” located anywhere in the file system. - Name string `json:"name"` - - // The name of the file without the path. - Display string `json:"display"` - - // Path is the path to the file within the location. E.g. - //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” - // and “subfolder” relative to the root of the location. - Path string `json:"path"` - - // Type of file. model or machinecode. Or folder if it’s a folder, in - // which case the children node will be populated. - Type string `json:"type"` - - // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` - // for .stl files, or `["machinecode", "gcode"]` for .gcode files. - // `["folder"]` for folders. - TypePath []string `json:"typePath"` - - - - - // Additional properties depend on type. For a type value of folder, see Folders. For any other value see Files. - - // * Folders - // --children - // --size - - - - // * Files - // Hash is the MD5 hash of the file. Only available for `local` files. - Hash string `json:"hash"` - - // Size of the file in bytes. Only available for `local` files or `sdcard` - // files if the printer supports file sizes for sd card files. - Size uint64 `json:"size"` - - // Date when this file was uploaded. Only available for `local` files. - Date JSONTime `json:"date"` - - // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, - // `sdcard` when stored on the printer’s SD card (if available). - Origin string `json:"origin"` - - // Refs references relevant to this file, left out in abridged version. - Refs Reference `json:"refs"` - - // GCodeAnalysis information from the analysis of the GCODE file, if - // available. Left out in abridged version. - GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` - - - - - // * Additional properties not listed in the SDK... - - // Print information from the print stats of a file. - Print PrintStats `json:"print"` - - - // Relative path to the preview thumbnail image (if it exists) - // The PrusaSlicer Thumbnails plug-in is required or this. - Thumbnail string `json:"thumbnail"` -} - -// IsFolder it returns true if the file is a folder. -func (response *FileResponse) IsFolder() bool { - if len(response.TypePath) == 1 && response.TypePath[0] == "folder" { - return true - } - - return false -} - -const URIFiles = "/api/files" - // Do sends an API request and returns the API response -func (request *FileRequest) Do(c *Client) (*FileResponse, error) { +func (request *FileRequest) Do(c *Client) (*dataModels.FileResponse, error) { uri := fmt.Sprintf("%s/%s/%s?recursive=%t", - URIFiles, + FilesApiUri, request.Location, request.Filename, request.Recursive, ) - bytes, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) + bytes, err := c.doJsonRequest("GET", uri, nil, FilesLocationGETErrors) if err != nil { return nil, err } - response := &FileResponse{} + response := &dataModels.FileResponse{} if err := json.Unmarshal(bytes, response); err != nil { return nil, err } diff --git a/octoprintApis/FilesRequest.go b/octoprintApis/FilesRequest.go new file mode 100755 index 00000000..335fb2aa --- /dev/null +++ b/octoprintApis/FilesRequest.go @@ -0,0 +1,47 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + // "mime/multipart" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// FilesRequest retrieve information regarding all files currently available and +// regarding the disk space still available locally in the system. +type FilesRequest struct { + // Location is the target location . + Location dataModels.Location + + // Recursive if set to true, return all files and folders recursively. + // Otherwise only return items on same level. + Recursive bool +} + +// Do sends an API request and returns the API response. +func (cmd *FilesRequest) Do(c *Client) (*dataModels.FilesResponse, error) { + uri := fmt.Sprintf("%s?recursive=%t", FilesApiUri, cmd.Recursive) + if cmd.Location != "" { + uri = fmt.Sprintf("%s/%s?recursive=%t", FilesApiUri, cmd.Location, cmd.Recursive) + } + + b, err := c.doJsonRequest("GET", uri, nil, FilesLocationGETErrors) + if err != nil { + return nil, err + } + + r := &dataModels.FilesResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + if len(r.Children) > 0 { + r.Files = r.Children + } + + return r, err +} diff --git a/octoprintApis/FullStateRequest.go b/octoprintApis/FullStateRequest.go index 90112605..80a2c431 100755 --- a/octoprintApis/FullStateRequest.go +++ b/octoprintApis/FullStateRequest.go @@ -4,11 +4,15 @@ import ( // "bytes" "encoding/json" "fmt" - // "io" - "log" + // "log" "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + +const URIPrinter = "/api/printer" + // FullStateRequest retrieves the current state of the printer. type FullStateRequest struct { // bytes if true retrieve the temperature history. @@ -23,22 +27,8 @@ type FullStateRequest struct { Exclude []string } -// FullStateResponse contains informantion about the current state of the printer. -type FullStateResponse struct { - // TemperatureStateResponse is the printer’s temperature state data. - Temperature TemperatureStateResponse `json:"temperature"` - - // SD is the printer’s sd state data. - SD SDState `json:"sd"` - - // State is the printer’s general state. - State PrinterState `json:"state"` -} - -const URIPrinter = "/api/printer" - // Do sends an API request and returns the API response. -func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { +func (cmd *FullStateRequest) Do(c *Client) (*dataModels.FullStateResponse, error) { uri := fmt.Sprintf( "%s?history=%t&limit=%d&exclude=%s", URIPrinter, @@ -47,7 +37,7 @@ func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { strings.Join(cmd.Exclude, ","), ) - log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) + // log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state /* { @@ -80,12 +70,12 @@ func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { */ - bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) + bytes, err := c.doJsonRequest("GET", uri, nil, PrintErrors) if err != nil { return nil, err } - response := &FullStateResponse{} + response := &dataModels.FullStateResponse{} if err := json.Unmarshal(bytes, response); err != nil { return nil, err } diff --git a/octoprintApis/JobRequest.go b/octoprintApis/JobRequest.go index 23797551..8e5d614c 100755 --- a/octoprintApis/JobRequest.go +++ b/octoprintApis/JobRequest.go @@ -5,39 +5,23 @@ import ( "encoding/json" // "io" // "log" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + // JobRequest retrieve information about the current job (if there is one). type JobRequest struct{} - -// Job information response -// https://docs.octoprint.org/en/master/api/job.html#job-information-response - -// JobResponse is the response from a job command. -type JobResponse struct { - // Job contains information regarding the target of the current print job. - Job JobInformation `json:"job"` - - // Progress contains information regarding the progress of the current job. - Progress ProgressInformation `json:"progress"` - - //State StateInformation `json:"state"` - State string `json:"state"` -} - -// https://docs.octoprint.org/en/master/api/job.html -const JobTool = "/api/job" - // Do sends an API request and returns the API response. -func (cmd *JobRequest) Do(client *Client) (*JobResponse, error) { - bytes, err := client.doJSONRequest("GET", JobTool, nil, nil) +func (cmd *JobRequest) Do(client *Client) (*dataModels.JobResponse, error) { + bytes, err := client.doJsonRequest("GET", JobApiUri, nil, nil) if err != nil { return nil, err } - response := &JobResponse{} + response := &dataModels.JobResponse{} if err := json.Unmarshal(bytes, response); err != nil { return nil, err } diff --git a/octoprintApis/LICENSE b/octoprintApis/LICENSE old mode 100644 new mode 100755 diff --git a/octoprintApis/NotificationRequest.go b/octoprintApis/NotificationRequest.go new file mode 100755 index 00000000..ff6b2637 --- /dev/null +++ b/octoprintApis/NotificationRequest.go @@ -0,0 +1,30 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "log" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +type NotificationRequest struct { + Command string `json:"command"` +} + +func (cmd *NotificationRequest) Do(c *Client) (*dataModels.NotificationResponse, error) { + target := fmt.Sprintf("%s?command=get_notification", PluginZBoltOctoScreenApiUri) + bytes, err := c.doJsonRequest("GET", target, nil, ConnectionErrors) + if err != nil { + return nil, err + } + + response := &dataModels.NotificationResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/OctoScreenSettingsRequest.go b/octoprintApis/OctoScreenSettingsRequest.go new file mode 100755 index 00000000..5aea65dc --- /dev/null +++ b/octoprintApis/OctoScreenSettingsRequest.go @@ -0,0 +1,28 @@ +package octoprintApis + +import ( + "encoding/json" + "fmt" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +type OctoScreenSettingsRequest struct { + Command string `json:"command"` +} + +func (cmd *OctoScreenSettingsRequest) Do(c *Client) (*dataModels.OctoScreenSettingsResponse, error) { + target := fmt.Sprintf("%s?command=get_settings", PluginZBoltOctoScreenApiUri) + bytes, err := c.doJsonRequest("GET", target, nil, ConnectionErrors) + if err != nil { + return nil, err + } + + response := &dataModels.OctoScreenSettingsResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/PauseRequest.go b/octoprintApis/PauseRequest.go new file mode 100755 index 00000000..ca6c6c28 --- /dev/null +++ b/octoprintApis/PauseRequest.go @@ -0,0 +1,41 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "io" + // "log" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// PauseRequest pauses/resumes/toggles the current print job. +type PauseRequest struct { + // Action specifies which action to take. + // In order to stay backwards compatible to earlier iterations of this API, + // the default action to take if no action parameter is supplied is to + // toggle the print job status. + Action dataModels.PauseAction `json:"action"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PauseRequest) Do(c *Client) error { + buffer := bytes.NewBuffer(nil) + if err := cmd.encode(buffer); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", JobApiUri, buffer, JobToolErrors) + return err +} + +func (cmd *PauseRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PauseRequest + }{ + Command: "pause", + PauseRequest: *cmd, + }) +} diff --git a/octoprintApis/PluginManagerInfoRequest.go b/octoprintApis/PluginManagerInfoRequest.go new file mode 100755 index 00000000..c68eafbc --- /dev/null +++ b/octoprintApis/PluginManagerInfoRequest.go @@ -0,0 +1,42 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "log" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +const pluginManagerRequestURI = "/api/plugin/pluginmanager" + +// PluginManagerInfoRequest - +type PluginManagerInfoRequest struct { + Command string `json:"command"` +} + +// Do - +func (cmd *PluginManagerInfoRequest) Do(c *Client) (*dataModels.PluginManagerInfoResponse, error) { + cmd.Command = "get_settings" + + params := bytes.NewBuffer(nil) + if err := json.NewEncoder(params).Encode(cmd); err != nil { + log.Println("plugin_manager.Do() - Encode() failed") + return nil, err + } + + b, err := c.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) + if err != nil { + log.Println("plugin_manager.Do() - doJsonRequest() failed") + return nil, err + } + + r := &dataModels.PluginManagerInfoResponse{} + if err := json.Unmarshal(b, r); err != nil { + log.Println("plugin_manager.Do() - Unmarshal() failed") + return nil, err + } + + return r, err +} diff --git a/octoprintApis/PrintHeadHomeRequest.go b/octoprintApis/PrintHeadHomeRequest.go new file mode 100755 index 00000000..2f565819 --- /dev/null +++ b/octoprintApis/PrintHeadHomeRequest.go @@ -0,0 +1,40 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// PrintHeadHomeRequest homes the print head in all of the given axes. +type PrintHeadHomeRequest struct { + // Axes is a list of axes which to home. + Axes []dataModels.Axis `json:"axes"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PrintHeadHomeRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterPrintHeadApiUri, b, PrintHeadJobErrors) + return err +} + +func (cmd *PrintHeadHomeRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PrintHeadHomeRequest + }{ + Command: "home", + PrintHeadHomeRequest: *cmd, + }) +} diff --git a/octoprintApis/PrintHeadJogRequest.go b/octoprintApis/PrintHeadJogRequest.go new file mode 100755 index 00000000..ee0c3714 --- /dev/null +++ b/octoprintApis/PrintHeadJogRequest.go @@ -0,0 +1,60 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// PrintHeadJogRequest jogs the print head (relatively) by a defined amount in +// one or more axes. +type PrintHeadJogRequest struct { + // X is the amount distance to travel in mm or coordinate to jog print head + // on x axis. + X float64 `json:"x,omitempty"` + + // Y is the amount distance to travel in mm or coordinate to jog print head + // on y axis. + Y float64 `json:"y,omitempty"` + + // Z is the amount distance to travel in mm.or coordinate to jog print head + // on x axis. + Z float64 `json:"z,omitempty"` + + // Absolute is whether to move relative to current position (provided axes + // values are relative amounts) or to absolute position (provided axes + // values are coordinates) + IsAbsolute bool `json:"absolute"` + + // Speed at which to move in mm/s. If not provided, minimum speed for all + // selected axes from printer profile will be used. + Speed int `json:"speed,omitempty"` +} + +// Do sends an API request and returns an error if any. +func (cmd *PrintHeadJogRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterPrintHeadApiUri, b, PrintHeadJobErrors) + + return err +} + +func (cmd *PrintHeadJogRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + PrintHeadJogRequest + }{ + Command: "jog", + PrintHeadJogRequest: *cmd, + }) +} diff --git a/octoprintApis/PrinterProfilesRequest.go b/octoprintApis/PrinterProfilesRequest.go old mode 100644 new mode 100755 index 74fc19bb..675f5bae --- a/octoprintApis/PrinterProfilesRequest.go +++ b/octoprintApis/PrinterProfilesRequest.go @@ -3,22 +3,25 @@ package octoprintApis import ( "encoding/json" "fmt" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + // SettingsRequest retrieves the current configuration of OctoPrint. type PrinterProfilesRequest struct { Id string } // Do sends an API request and returns the API response. -func (cmd *PrinterProfilesRequest) Do(c *Client) (*PrinterProfile, error) { +func (cmd *PrinterProfilesRequest) Do(c *Client) (*dataModels.PrinterProfileResponse, error) { uri := fmt.Sprintf("/api/printerprofiles/%s", cmd.Id) - b, err := c.doJSONRequest("GET", uri, nil, nil) + b, err := c.doJsonRequest("GET", uri, nil, nil) if err != nil { return nil, err } - r := &PrinterProfile{} + r := &dataModels.PrinterProfileResponse{} if err := json.Unmarshal(b, r); err != nil { return nil, err } diff --git a/octoprintApis/README.md b/octoprintApis/README.md old mode 100644 new mode 100755 diff --git a/octoprintApis/RestartRequest.go b/octoprintApis/RestartRequest.go new file mode 100755 index 00000000..5b4c9b20 --- /dev/null +++ b/octoprintApis/RestartRequest.go @@ -0,0 +1,29 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "io" + // "log" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// RestartRequest restart the print of the currently selected file from the +// beginning. There must be an active print job for this to work and the print +// job must currently be paused +type RestartRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *RestartRequest) Do(c *Client) error { + payload := map[string]string{"command": "restart"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", JobApiUri, buffer, JobToolErrors) + return err +} diff --git a/octoprintApis/RunZOffsetCalibrationRequest.go b/octoprintApis/RunZOffsetCalibrationRequest.go new file mode 100755 index 00000000..415089c5 --- /dev/null +++ b/octoprintApis/RunZOffsetCalibrationRequest.go @@ -0,0 +1,26 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "log" +) + + +type RunZOffsetCalibrationRequest struct { + Command string `json:"command"` +} + +func (cmd *RunZOffsetCalibrationRequest) Do(c *Client) error { + cmd.Command = "run_zoffset_calibration" + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + log.Println("zbolt.Do() 1 - NewEncoder() failed") + return err + } + + _, err := c.doJsonRequest("POST", PluginZBoltOctoScreenApiUri, b, ConnectionErrors) + return err +} diff --git a/octoprintApis/SdInitRequest.go b/octoprintApis/SdInitRequest.go new file mode 100755 index 00000000..8231f6a8 --- /dev/null +++ b/octoprintApis/SdInitRequest.go @@ -0,0 +1,23 @@ +package octoprintApis + +import ( + // "bytes" + // "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// SdInitRequest initializes the printer’s SD card, making it available for use. +// This also includes an initial retrieval of the list of files currently stored +// on the SD card. +type SdInitRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SdInitRequest) Do(c *Client) error { + return doCommandRequest(c, PrinterSdApiUri, "init", PrintSdErrors) +} diff --git a/octoprintApis/SdRefreshRequest.go b/octoprintApis/SdRefreshRequest.go new file mode 100755 index 00000000..c8fdb270 --- /dev/null +++ b/octoprintApis/SdRefreshRequest.go @@ -0,0 +1,21 @@ +package octoprintApis + +import ( + // "bytes" + // "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// SdRefreshRequest Refreshes the list of files stored on the printer’s SD card. +type SdRefreshRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SdRefreshRequest) Do(c *Client) error { + return doCommandRequest(c, PrinterSdApiUri, "refresh", PrintSdErrors) +} diff --git a/octoprintApis/SdReleaseRequest.go b/octoprintApis/SdReleaseRequest.go new file mode 100755 index 00000000..15156368 --- /dev/null +++ b/octoprintApis/SdReleaseRequest.go @@ -0,0 +1,23 @@ +package octoprintApis + +import ( + // "bytes" + // "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// SdReleaseRequest releases the SD card from the printer. The reverse operation +// to init. After issuing this command, the SD card won’t be available anymore, +// hence and operations targeting files stored on it will fail. +type SdReleaseRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *SdReleaseRequest) Do(c *Client) error { + return doCommandRequest(c, PrinterSdApiUri, "release", PrintSdErrors) +} diff --git a/octoprintApis/SdStateRequest.go b/octoprintApis/SdStateRequest.go new file mode 100755 index 00000000..b2e6afa2 --- /dev/null +++ b/octoprintApis/SdStateRequest.go @@ -0,0 +1,32 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + // "fmt" + // "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// SdStateRequest retrieves the current state of the printer’s SD card. For this +// request no authentication is needed. +type SdStateRequest struct{} + +// Do sends an API request and returns the API response. +func (cmd *SdStateRequest) Do(c *Client) (*dataModels.SdState, error) { + b, err := c.doJsonRequest("GET", PrinterSdApiUri, nil, PrintSdErrors) + if err != nil { + return nil, err + } + + r := &dataModels.SdState{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/SelectFileRequest.go b/octoprintApis/SelectFileRequest.go index fabb9135..7e50289e 100755 --- a/octoprintApis/SelectFileRequest.go +++ b/octoprintApis/SelectFileRequest.go @@ -5,15 +5,17 @@ import ( "encoding/json" "fmt" "io" - // "mime/multipart" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + // SelectFileRequest selects a file for printing. type SelectFileRequest struct { // Location is target location on which to send the command for is located, // either local (for OctoPrint’s uploads folder) or sdcard for the // printer’s SD card (if available). - Location Location `json:"-"` + Location dataModels.Location `json:"-"` // Path of the file for which to issue the command. Path string `json:"-"` @@ -32,8 +34,8 @@ func (cmd *SelectFileRequest) Do(c *Client) error { return err } - uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) - _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) + uri := fmt.Sprintf("%s/%s/%s", FilesApiUri, cmd.Location, cmd.Path) + _, err := c.doJsonRequest("POST", uri, b, FilesLocationPathPOSTErrors) return err } diff --git a/octoprintApis/StartRequest.go b/octoprintApis/StartRequest.go new file mode 100755 index 00000000..475ad1bf --- /dev/null +++ b/octoprintApis/StartRequest.go @@ -0,0 +1,27 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "io" + // "log" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// StartRequest starts the print of the currently selected file. +type StartRequest struct{} + +// Do sends an API request and returns an error if any. +func (cmd *StartRequest) Do(c *Client) error { + payload := map[string]string{"command": "start"} + + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(payload); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", JobApiUri, buffer, JobToolErrors) + return err +} diff --git a/octoprintApis/StatusMapping.go b/octoprintApis/StatusMapping.go new file mode 100755 index 00000000..8591e05c --- /dev/null +++ b/octoprintApis/StatusMapping.go @@ -0,0 +1,24 @@ +package octoprintApis + +import ( + // "errors" + "fmt" + // "io" + // "io/ioutil" + // "log" + // "net/http" + // "net/url" + // "time" +) + + +type StatusMapping map[int]string + +func (this *StatusMapping) Error(code int) error { + err, ok := (*this)[code] + if ok { + return fmt.Errorf(err) + } + + return nil +} diff --git a/octoprintApis/TemperatureDataRequest.go b/octoprintApis/TemperatureDataRequest.go new file mode 100755 index 00000000..5a66c484 --- /dev/null +++ b/octoprintApis/TemperatureDataRequest.go @@ -0,0 +1,67 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// FullStateRequest retrieves the current state of the printer. +type TemperatureDataRequest struct { + // bytes if true retrieve the temperature history. + // IncludeHistory bool + + // Limit limits the amount of returned history data points. + // Limit int + + // Exclude list of fields to exclude from the response (e.g. if not + // needed by the client). Valid values to supply here are `temperature`, + // `sd` and `state`. + // Exclude []string +} + +// Do sends an API request and returns the API response. +func (cmd *TemperatureDataRequest) Do(c *Client) (*dataModels.TemperatureDataResponse, error) { + uri := fmt.Sprintf( + "%s?history=false&exclude=sd,state", + URIPrinter, + ) + + // log.Printf("TODO-Remove: StateRequest (TemperatureDataResponse) uri is: %s", uri) + //StateRequest uri is: %s /api/printer?history=false&exclude=sd,state + /* + { + "temperature": { + "bed": { + "actual": 26.9, + "offset": 0, + "target": 0.0 + }, + "tool0": { + "actual": 35.4, + "offset": 0, + "target": 0.0 + } + } + } + */ + + + bytes, err := c.doJsonRequest("GET", uri, nil, PrintErrors) + if err != nil { + return nil, err + } + + response := &dataModels.TemperatureDataResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + return nil, err + } + + return response, err +} diff --git a/octoprintApis/ToolExtrudeRequest.go b/octoprintApis/ToolExtrudeRequest.go new file mode 100755 index 00000000..eecf50fe --- /dev/null +++ b/octoprintApis/ToolExtrudeRequest.go @@ -0,0 +1,42 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolExtrudeRequest extrudes the given amount of filament from the currently +// selected tool. +type ToolExtrudeRequest struct { + // Amount is the amount of filament to extrude in mm. May be negative to + // retract. + Amount int `json:"amount"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolExtrudeRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *ToolExtrudeRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolExtrudeRequest + }{ + Command: "extrude", + ToolExtrudeRequest: *cmd, + }) +} diff --git a/octoprintApis/ToolFlowRateRequest.go b/octoprintApis/ToolFlowRateRequest.go new file mode 100755 index 00000000..c3f78420 --- /dev/null +++ b/octoprintApis/ToolFlowRateRequest.go @@ -0,0 +1,40 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolFlowRateRequest changes the flow rate factor to apply to extrusion of the tool. +type ToolFlowRateRequest struct { + // Factor is the new factor, percentage as integer, between 75 and 125%. + Factor int `json:"factor"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolFlowRateRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *ToolFlowRateRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolFlowRateRequest + }{ + Command: "flowrate", + ToolFlowRateRequest: *cmd, + }) +} diff --git a/octoprintApis/ToolOffsetRequest.go b/octoprintApis/ToolOffsetRequest.go new file mode 100755 index 00000000..2dbf71a7 --- /dev/null +++ b/octoprintApis/ToolOffsetRequest.go @@ -0,0 +1,41 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolOffsetRequest sets the given temperature offset on the printer’s tools. +type ToolOffsetRequest struct { + // Offset is offset(s) to set, key must match the format tool{n} with n + // being the tool’s index starting with 0. + Offsets map[string]float64 `json:"offsets"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolOffsetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *ToolOffsetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolOffsetRequest + }{ + Command: "offset", + ToolOffsetRequest: *cmd, + }) +} diff --git a/octoprintApis/ToolSelectRequest.go b/octoprintApis/ToolSelectRequest.go new file mode 100755 index 00000000..7716d9a6 --- /dev/null +++ b/octoprintApis/ToolSelectRequest.go @@ -0,0 +1,41 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolSelectRequest selects the printer’s current tool. +type ToolSelectRequest struct { + // Tool to select, format tool{n} with n being the tool’s index starting + // with 0. + Tool string `json:"tool"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolSelectRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *ToolSelectRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolSelectRequest + }{ + Command: "select", + ToolSelectRequest: *cmd, + }) +} diff --git a/octoprintApis/ToolStateRequest.go b/octoprintApis/ToolStateRequest.go new file mode 100755 index 00000000..353d0acf --- /dev/null +++ b/octoprintApis/ToolStateRequest.go @@ -0,0 +1,61 @@ +package octoprintApis + +import ( + // "bytes" + "encoding/json" + "fmt" + // "io" + // "log" + // "strings" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolStateRequest retrieves the current temperature data (actual, target and +// offset) plus optionally a (limited) history (actual, target, timestamp) for +// all of the printer’s available tools. +type ToolStateRequest struct { + // History if true retrieve the temperature history. + IncludeHistory bool + + // Limit limtis amount of returned history data points. + Limit int +} + +// Do sends an API request and returns the API response. +func (cmd *ToolStateRequest) Do(c *Client) (*dataModels.TemperatureStateResponse, error) { + uri := fmt.Sprintf("%s?history=%t&limit=%d", PrinterToolApiUri, cmd.IncludeHistory, cmd.Limit) + + // log.Printf("TODO-Remove: ToolStateRequest uri is: %s", uri) + //ToolStateRequest uri is: %s /api/printer/tool?history=true&limit=1 + /* + { + "history": [ + { + "tool0": { + "actual": 38.0, + "target": 0.0 + } + } + ], + "tool0": { + "actual": 38.0, + "offset": 0, + "target": 0.0 + } + } + */ + + b, err := c.doJsonRequest("GET", uri, nil, nil) + if err != nil { + return nil, err + } + + r := &dataModels.TemperatureStateResponse{} + if err := json.Unmarshal(b, &r); err != nil { + return nil, err + } + + return r, err +} diff --git a/octoprintApis/ToolTargetRequest.go b/octoprintApis/ToolTargetRequest.go new file mode 100755 index 00000000..546bbb99 --- /dev/null +++ b/octoprintApis/ToolTargetRequest.go @@ -0,0 +1,41 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "io" + // "log" + // "strings" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// ToolTargetRequest sets the given target temperature on the printer’s tools. +type ToolTargetRequest struct { + // Target temperature(s) to set, key must match the format tool{n} with n + // being the tool’s index starting with 0. + Targets map[string]float64 `json:"targets"` +} + +// Do sends an API request and returns an error if any. +func (cmd *ToolTargetRequest) Do(c *Client) error { + b := bytes.NewBuffer(nil) + if err := cmd.encode(b); err != nil { + return err + } + + _, err := c.doJsonRequest("POST", PrinterToolApiUri, b, PrintToolErrors) + return err +} + +func (cmd *ToolTargetRequest) encode(w io.Writer) error { + return json.NewEncoder(w).Encode(struct { + Command string `json:"command"` + ToolTargetRequest + }{ + Command: "target", + ToolTargetRequest: *cmd, + }) +} diff --git a/octoprintApis/UploadFileRequest.go b/octoprintApis/UploadFileRequest.go new file mode 100755 index 00000000..2b3a581a --- /dev/null +++ b/octoprintApis/UploadFileRequest.go @@ -0,0 +1,92 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "mime/multipart" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +// UploadFileRequest uploads a file to the selected location or create a new +// empty folder on it. +type UploadFileRequest struct { + // Location is the target location to which to upload the file. Currently + // only `local` and `sdcard` are supported here, with local referring to + // OctoPrint’s `uploads` folder and `sdcard` referring to the printer’s + // SD card. If an upload targets the SD card, it will also be stored + // locally first. + Location dataModels.Location + + // Select whether to select the file directly after upload (true) or not + // (false). Optional, defaults to false. Ignored when creating a folder. + Select bool + + //Print whether to start printing the file directly after upload (true) or + // not (false). If set, select is implicitely true as well. Optional, + // defaults to false. Ignored when creating a folder. + Print bool + b *bytes.Buffer + w *multipart.Writer +} + +// AddFile adds a new file to be uploaded from a given reader. +func (req *UploadFileRequest) AddFile(filename string, r io.Reader) error { + w, err := req.writer().CreateFormFile("file", filename) + if err != nil { + return err + } + + _, err = io.Copy(w, r) + return err + +} + +func (req *UploadFileRequest) writer() *multipart.Writer { + if req.w == nil { + req.b = bytes.NewBuffer(nil) + req.w = multipart.NewWriter(req.b) + } + + return req.w +} + +// AddFolder adds a new folder to be created. +func (req *UploadFileRequest) AddFolder(folder string) error { + return req.writer().WriteField("foldername", folder) +} + +// Do sends an API request and returns the API response. +func (req *UploadFileRequest) Do(c *Client) (*dataModels.UploadFileResponse, error) { + req.addSelectPrintAndClose() + + uri := fmt.Sprintf("%s/%s", FilesApiUri, req.Location) + b, err := c.doRequest("POST", uri, req.w.FormDataContentType(), req.b, FilesLocationPOSTErrors) + if err != nil { + return nil, err + } + + r := &dataModels.UploadFileResponse{} + if err := json.Unmarshal(b, r); err != nil { + return nil, err + } + + return r, err +} + +func (req *UploadFileRequest) addSelectPrintAndClose() error { + err := req.writer().WriteField("select", fmt.Sprintf("%t", req.Select)) + if err != nil { + return err + } + + err = req.writer().WriteField("print", fmt.Sprintf("%t", req.Print)) + if err != nil { + return err + } + + return req.writer().Close() +} diff --git a/octoprintApis/ZOffsetRequest.go b/octoprintApis/ZOffsetRequest.go new file mode 100755 index 00000000..cd6eb12b --- /dev/null +++ b/octoprintApis/ZOffsetRequest.go @@ -0,0 +1,64 @@ +package octoprintApis + +import ( + "bytes" + "encoding/json" + // "fmt" + "log" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +type ZOffsetRequest struct { + Command string `json:"command"` + Tool int `json:"tool"` +} + +func (cmd *ZOffsetRequest) Do(c *Client) (*dataModels.ZOffsetResponse, error) { + cmd.Command = "get_z_offset" + + params := bytes.NewBuffer(nil) + if err := json.NewEncoder(params).Encode(cmd); err != nil { + log.Println("zbolt.Do() 3 - Encode() failed") + return nil, err + } + + // b, err := c.doJsonRequest("POST", URIZBoltRequest, params, ConnectionErrors) + b, err := c.doJsonRequest("GET", PluginZBoltApiUri, params, ConnectionErrors) + if err != nil { + log.Println("zbolt.Do() 3 - doJsonRequest() failed") + return nil, err + } + + r := &dataModels.ZOffsetResponse{} + if err := json.Unmarshal(b, r); err != nil { + log.Println("zbolt.Do() 3 - Unmarshal() failed") + return nil, err + } + + return r, err +} + + + + +// SetZOffsetRequest - retrieves the current configuration of OctoPrint. +type SetZOffsetRequest struct { + Command string `json:"command"` + Tool int `json:"tool"` + Value float64 `json:"value"` +} + +func (cmd *SetZOffsetRequest) Do(c *Client) error { + cmd.Command = "set_z_offset" + + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(cmd); err != nil { + log.Println("zbolt.Do() 2 - Encode() failed") + return err + } + + _, err := c.doJsonRequest("POST", PluginZBoltApiUri, b, ConnectionErrors) + return err +} diff --git a/octoprintApis/_examples/state/main.go b/octoprintApis/_examples/state/main.go old mode 100644 new mode 100755 index 0d30df2b..376c023f --- a/octoprintApis/_examples/state/main.go +++ b/octoprintApis/_examples/state/main.go @@ -4,20 +4,20 @@ import ( "fmt" "os" - "github.com/mgutz/logxi/v1" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/mgutz/logxi/v1" ) func main() { baseURL, apiKey := os.Args[1], os.Args[2] - c := octoprintApis.NewClient(baseURL, apiKey) + c := octoprint.NewClient(baseURL, apiKey) printConnectionState(c) printTemperature(c) } -func printConnectionState(c *octoprintApis.Client) { - r := octoprintApis.ConnectionRequest{} +func printConnectionState(c *octoprint.Client) { + r := octoprint.ConnectionRequest{} s, err := r.Do(c) if err != nil { log.Error("error requesting connection state: %s", err) @@ -26,8 +26,8 @@ func printConnectionState(c *octoprintApis.Client) { fmt.Printf("Connection State: %q\n", s.Current.State) } -func printTemperature(c *octoprintApis.Client) { - r := octoprintApis.StateRequest{} +func printTemperature(c *octoprint.Client) { + r := octoprint.StateRequest{} s, err := r.Do(c) if err != nil { log.Error("error requesting state: %s", err) diff --git a/octoprintApis/client.go b/octoprintApis/client.go index c5a55ab8..1e67ac30 100755 --- a/octoprintApis/client.go +++ b/octoprintApis/client.go @@ -5,15 +5,19 @@ import ( "fmt" "io" "io/ioutil" - "log" + // "log" "net/http" "net/url" "time" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + // ErrUnauthorized missing or invalid API key var ErrUnauthorized = errors.New("Missing or invalid API key") + // A Client manages communication with the OctoPrint API. type Client struct { // Endpoint address to the OctoPrint REST API server. @@ -22,8 +26,8 @@ type Client struct { // APIKey used to connect to the OctoPrint REST API server. APIKey string - // TODO: - c *http.Client + // HTTP client connection. + httpClient *http.Client } // NewClient returns a new OctoPrint API client with provided base URL and API @@ -34,7 +38,7 @@ func NewClient(endpoint, apiKey string) *Client { return &Client{ Endpoint: endpoint, APIKey: apiKey, - c: &http.Client{ + httpClient: &http.Client{ Timeout: time.Second * 3, Transport: &http.Transport{ DisableKeepAlives: true, @@ -43,24 +47,23 @@ func NewClient(endpoint, apiKey string) *Client { } } -func (c *Client) doJSONRequest( - method, target string, body io.Reader, m StatusMapping, +func (this *Client) doJsonRequest( + method string, + target string, + body io.Reader, + statusMapping StatusMapping, ) ([]byte, error) { - return c.doRequest(method, target, "application/json", body, m) + return this.doRequest(method, target, "application/json", body, statusMapping) } -func (c *Client) doJSONRequestWithLogging( - method, target string, body io.Reader, m StatusMapping, +func (this *Client) doRequest( + method string, + target string, + contentType string, + body io.Reader, + statusMapping StatusMapping, ) ([]byte, error) { - return c.doRequestWithLogging(method, target, "application/json", body, m) -} - - - -func (c *Client) doRequest( - method, target, contentType string, body io.Reader, m StatusMapping, -) ([]byte, error) { - req, err := http.NewRequest(method, joinURL(c.Endpoint, target), body) + req, err := http.NewRequest(method, joinUrl(this.Endpoint, target), body) if err != nil { return nil, err } @@ -72,167 +75,50 @@ func (c *Client) doRequest( req.Header.Add("Content-Type", contentType) } - req.Header.Add("X-Api-Key", c.APIKey) - resp, err := c.c.Do(req) + req.Header.Add("X-Api-Key", this.APIKey) + resp, err := this.httpClient.Do(req) if err != nil { return nil, err } - return c.handleResponse(resp, m) + return this.handleResponse(resp, statusMapping) } - - - -func (c *Client) doRequestWithLogging( - method, target, contentType string, body io.Reader, m StatusMapping, +func (this *Client) handleResponse( + httpResponse *http.Response, + statusMapping StatusMapping, ) ([]byte, error) { + defer httpResponse.Body.Close() - - log.Println("Now in Client.doRequest()") - - - - req, err := http.NewRequest(method, joinURL(c.Endpoint, target), body) - if err != nil { - log.Println("Client.doRequest() - NewRequest() failed") - return nil, err - } - - req.Header.Add("Host", "localhost:5000") - req.Header.Add("Accept", "*/*") - req.Header.Add("User-Agent", fmt.Sprintf("go-octoprint/%s", Version)) - if contentType != "" { - req.Header.Add("Content-Type", contentType) - } - - req.Header.Add("X-Api-Key", c.APIKey) - - - resp, err := c.c.Do(req) - // resp, err := c.c.DoWithLogging(req) - if err != nil { - log.Println("Client.doRequest() - c.c.Do() failed") - return nil, err - } - - - - - - log.Println("!!! Now in Client.doRequest() - finished calling DoWithLogging() !!!") - if resp != nil { - log.Printf("!!! Now in Client.doRequest() - resp.Status: %s", resp.Status) - log.Printf("!!! Now in Client.doRequest() - resp.StatusCode: %d", resp.StatusCode) - } else { - log.Printf("!!! Now in Client.doRequest() - resp was nil") - } - - if err != nil { - log.Printf("!!! Now in Client.doRequest() - err: %s", err.Error()) - } else { - log.Printf("!!! Now in Client.doRequest() - err was nil") - } - return nil, err - - - - // return c.handleResponseWithLogging(resp, m) -} - - - -func (c *Client) handleResponse(r *http.Response, m StatusMapping) ([]byte, error) { - defer r.Body.Close() - - if m != nil { - if err := m.Error(r.StatusCode); err != nil { + if statusMapping != nil { + if err := statusMapping.Error(httpResponse.StatusCode); err != nil { return nil, err } } - if r.StatusCode == 401 { + if httpResponse.StatusCode == 401 { return nil, ErrUnauthorized } - if r.StatusCode == 204 { + if httpResponse.StatusCode == 204 { return nil, nil } - body, err := ioutil.ReadAll(r.Body) + body, err := ioutil.ReadAll(httpResponse.Body) if err != nil { return nil, err } - if r.StatusCode >= 200 && r.StatusCode <= 209 { + if httpResponse.StatusCode >= 200 && httpResponse.StatusCode <= 209 { return body, nil } - return nil, fmt.Errorf("unexpected status code: %d", r.StatusCode) + return nil, fmt.Errorf("unexpected status code: %d", httpResponse.StatusCode) } - -func (c *Client) handleResponseWithLogging(r *http.Response, m StatusMapping) ([]byte, error) { - - log.Println("Now in Client.handleResponse()") - - defer r.Body.Close() - - if m != nil { - log.Println("Client.handleResponse() - m is nil") - - if err := m.Error(r.StatusCode); err != nil { - log.Println("Client.handleResponse() - m.Error is not nil and is: ", err) - log.Println("Client.handleResponse() - r.StatusCode: ", r.StatusCode) - return nil, err - } - } - - if r.StatusCode == 401 { - log.Println("Client.handleResponse() - status code is 401, returning") - return nil, ErrUnauthorized - } - - if r.StatusCode == 204 { - log.Println("Client.handleResponse() - status code is 204, returning") - return nil, nil - } - - body, err := ioutil.ReadAll(r.Body) - if err != nil { - log.Println("Client.handleResponse() - ReadAll() failed, err is: ", err) - return nil, err - } - - if r.StatusCode >= 200 && r.StatusCode <= 209 { - log.Println("Client.handleResponse() - status code appears to be good, returning") - return body, nil - } - - log.Println("Client.handleResponse() - looks like it failed, status code was ", r.StatusCode) - - - return nil, fmt.Errorf("unexpected status code: %d", r.StatusCode) -} - - - - - -func joinURL(base, uri string) string { +func joinUrl(base, uri string) string { u, _ := url.Parse(uri) b, _ := url.Parse(base) return b.ResolveReference(u).String() } - -type StatusMapping map[int]string - -func (m *StatusMapping) Error(code int) error { - err, ok := (*m)[code] - if ok { - return fmt.Errorf(err) - } - - return nil -} diff --git a/octoprintApis/common.go b/octoprintApis/common.go index 758e8e40..0679367a 100755 --- a/octoprintApis/common.go +++ b/octoprintApis/common.go @@ -1,1029 +1,3 @@ package octoprintApis -import ( - "encoding/json" - "strconv" - "strings" - "time" -) - var Version = "0.1" - -type Axis string - -const ( - XAxis Axis = "x" - YAxis Axis = "y" - ZAxis Axis = "z" -) - -// JobResponse is now in JobRequest.go -// // JobResponse is the response from a job command. -// type JobResponse struct { -// // Job contains information regarding the target of the current print job. -// Job JobInformation `json:"job"` - -// // Progress contains information regarding the progress of the current job. -// Progress ProgressInformation `json:"progress"` - -// //State StateInformation `json:"state"` -// State string `json:"state"` -// } - - - -// JobInformation i no in JobInformation.go -// // JobInformation contains information regarding the target of the current job. -// type JobInformation struct { -// // File is the file that is the target of the current print job. -// File FileResponse `json:"file"` - -// // EstimatedPrintTime is the estimated print time for the file, in seconds. -// EstimatedPrintTime float64 `json:"estimatedPrintTime"` - -// // LastPrintTime is the print time of the last print of the file, in seconds. -// LastPrintTime float64 `json:"lastPrintTime"` - -// // Filament contains Information regarding the estimated filament -// // usage of the print job. -// Filament struct { -// // Length of filament used, in mm -// Length float64 `json:"length"` -// // Volume of filament used, in cm³ -// Volume float64 `json:"volume"` -// } `json:"filament"` - -// FilePosition uint64 `json:"filepos"` -// } - - - -// ProgressInformation is now in ProgressInformation.go -// ProgressInformation contains information regarding the progress of the -// current print job. -// type ProgressInformation struct { -// // Completion percentage of completion of the current print job. -// Completion float64 `json:"completion"` - -// // FilePosition current position in the file being printed, in bytes -// // from the beginning. -// FilePosition uint64 `json:"filepos"` - -// // PrintTime is time already spent printing, in seconds -// PrintTime float64 `json:"printTime"` - -// // PrintTimeLeft is estimate of time left to print, in seconds -// PrintTimeLeft float64 `json:"printTimeLeft"` - -// // Origin of the current time left estimate -// PrintTimeLeftOrigin string `json:"printTimeLeftOrigin"` -// } - - - - -// TemperatureStateResponse is now in TemperatureStateResponse.go -// // TemperatureState is the printer’s temperature state data. -// type TemperatureStateResponse temperatureStateResponse - -// type temperatureStateResponse struct { -// // Current temperature stats. -// CurrentTemperatureData map[string]TemperatureData `json:"current"` - -// // Temperature history. -// History []*HistoricTemperatureData `json:"history"` -// } - -// func (r *TemperatureStateResponse) UnmarshalJSON(b []byte) error { -// var raw map[string]interface{} -// if err := json.Unmarshal(b, &raw); err != nil { -// return err -// } - -// history := raw["history"] -// delete(raw, "history") -// b, _ = json.Marshal(map[string]interface{}{ -// "current": raw, -// "history": history, -// }) - -// i := &temperatureStateResponse{} -// if err := json.Unmarshal(b, i); err != nil { -// return err -// } - -// *r = TemperatureStateResponse(*i) -// return nil -// } - -// TemperatureData is now in TemperatureData.go -// // TemperatureData is temperature stats for a tool. -// type TemperatureData struct { -// // Actual current temperature. -// Actual float64 `json:"actual"` - -// // Target temperature, may be nil if no target temperature is set. -// Target float64 `json:"target"` - -// // Offset currently configured temperature offset to apply, will be left -// // out for historic temperature information. -// Offset float64 `json:"offset"` -// } - -// PrinterState current state of the printer. -type PrinterState struct { - Text string `json:"text"` - Flags struct { - Operations bool `json:"operational"` - Paused bool `json:"paused"` - Printing bool `json:"printing"` - SDReady bool `json:"sdReady"` - Error bool `json:"error"` - Ready bool `json:"ready"` - ClosedOnError bool `json:"closedOrError"` - } `json:"flags"` -} - -// SDState is the state of the sd reader. -type SDState struct { - Ready bool `json:"ready"` -} - -// HistoricTemperatureData is temperature historic stats for a tool. -type HistoricTemperatureData historicTemperatureData -type historicTemperatureData struct { - // Time of this data point. - Time JSONTime `json:"time"` - - // Tools is temperature stats a set of tools. - Tools map[string]TemperatureData `json:"tools"` -} - -func (h *HistoricTemperatureData) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - - ts := raw["time"] - delete(raw, "time") - b, _ = json.Marshal(map[string]interface{}{ - "time": ts, - "tools": raw, - }) - - i := &historicTemperatureData{} - if err := json.Unmarshal(b, i); err != nil { - return err - } - - *h = HistoricTemperatureData(*i) - return nil -} - -// VersionResponse is the response from a job command. -type VersionResponse struct { - // API is the API version. - API string `json:"api"` - - // Server is the server version. - Server string `json:"server"` -} - -type ConnectionState string - -const ( - Operational ConnectionState = "Operational" -) - -// The states are based on: -// https://github.com/foosel/OctoPrint/blob/77753ca02602d3a798d6b0a22535e6fd69ff448a/src/octoprint/util/comm.py#L549 - -func (s ConnectionState) IsOperational() bool { - return strings.HasPrefix(string(s), "Operational") -} - -func (s ConnectionState) IsPrinting() bool { - return strings.HasPrefix(string(s), "Printing") || - strings.HasPrefix(string(s), "Starting") || - strings.HasPrefix(string(s), "Sending") || - strings.HasPrefix(string(s), "Paused") || - strings.HasPrefix(string(s), "Pausing") || - strings.HasPrefix(string(s), "Transfering") -} - -func (s ConnectionState) IsOffline() bool { - return strings.HasPrefix(string(s), "Offline") || - strings.HasPrefix(string(s), "Closed") -} - -func (s ConnectionState) IsError() bool { - return strings.HasPrefix(string(s), "Error") || - strings.HasPrefix(string(s), "Unknown") -} - -func (s ConnectionState) IsConnecting() bool { - return strings.HasPrefix(string(s), "Opening") || - strings.HasPrefix(string(s), "Detecting") || - strings.HasPrefix(string(s), "Connecting") || - strings.HasPrefix(string(s), "Detecting") -} - -// ConnectionResponse is the response from a connection command. -type ConnectionResponse struct { - Current struct { - // State current state of the connection. - State ConnectionState `json:"state"` - - // Port to connect to. - Port string `json:"port"` - - // BaudRate speed of the connection. - BaudRate int `json:"baudrate"` - - // PrinterProfile profile to use for connection. - PrinterProfile string `json:"printerProfile"` - } - - Options struct { - // Ports list of available ports. - Ports []string `json:"ports"` - - // BaudRates list of available speeds. - BaudRates []int `json:"baudrates"` - - // PrinterProfile list of available profiles. - PrinterProfiles []*Profile `json:"printerProfiles"` - - // PortPreference default port. - PortPreference string `json:"portPreference"` - - // BaudRatePreference default speed. - BaudRatePreference int `json:"baudratePreference"` - - // PrinterProfilePreference default profile. - PrinterProfilePreference string `json:"printerProfilePreference"` - - // Autoconnect whether to automatically connect to the printer on - // OctoPrint’s startup in the future. - Autoconnect bool `json:"autoconnect"` - } -} - -// Profile describe a printer profile. -type Profile struct { - // ID is the identifier of the profile. - ID string `json:"id"` - - // Name is the display name of the profile. - Name string `json:"name"` -} - -// FilesResponse is the response to a FilesRequest. -type FilesResponse struct { - // Files is the list of requested files. Might be an empty list if no files - // are available - Files []*FileResponse - Children []*FileResponse - - // Free is the amount of disk space in bytes available in the local disk - // space (refers to OctoPrint’s `uploads` folder). Only returned if file - // list was requested for origin `local` or all origins. - Free uint64 -} - -// FileInformation/FileResponse is now in FileRequest.go -// TODO: remove this commented code -// FileInformation contains information regarding a file. -// type FileInformation struct { -// // Name is name of the file without path. E.g. “file.gco” for a file -// // “file.gco” located anywhere in the file system. -// Name string `json:"name"` - -// // The name of the file without the path -// Display string `json:"display"` - -// // Path is the path to the file within the location. E.g. -// //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” -// // and “subfolder” relative to the root of the location. -// Path string `json:"path"` - -// // Type of file. model or machinecode. Or folder if it’s a folder, in -// // which case the children node will be populated. -// Type string `json:"type"` - -// // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` -// // for .stl files, or `["machinecode", "gcode"]` for .gcode files. -// // `["folder"]` for folders. -// TypePath []string `json:"typePath"` - -// // Hash is the MD5 hash of the file. Only available for `local` files. -// Hash string `json:"hash"` - -// // Size of the file in bytes. Only available for `local` files or `sdcard` -// // files if the printer supports file sizes for sd card files. -// Size uint64 `json:"size"` - -// // Date when this file was uploaded. Only available for `local` files. -// Date JSONTime `json:"date"` - -// // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, -// // `sdcard` when stored on the printer’s SD card (if available) -// Origin string `json:"origin"` - -// // Refs references relevant to this file, left out in abridged versio -// Refs Reference `json:"refs"` - -// // GCodeAnalysis information from the analysis of the GCODE file, if -// // available. Left out in abridged version. -// GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` - -// // Print information from the print stats of a file. -// Print PrintStats `json:"print"` -// } - -// // IsFolder it returns true if the file is a folder. -// func (f *FileInformation) IsFolder() bool { -// if len(f.TypePath) == 1 && f.TypePath[0] == "folder" { -// return true -// } - -// return false -// } - -// Reference of a file. -type Reference struct { - // Resource that represents the file or folder (e.g. for issuing commands - // to or for deleting) - Resource string `json:"resource"` - - // Download URL for the file. Never present for folders. - Download string `json:"download"` - - // Model from which this file was generated (e.g. an STL, currently not - // used). Never present for folders. - Model string `json:"model"` -} - -// GCodeAnalysisInformation Information from the analysis of the GCODE file. -type GCodeAnalysisInformation struct { - // EstimatedPrintTime is the estimated print time of the file, in seconds. - EstimatedPrintTime float64 `json:"estimatedPrintTime"` - - // Filament estimated usage of filament - Filament struct { - // Length estimated of filament used, in mm - Length uint32 `json:"length"` - - // Volume estimated of filament used, in cm³ - Volume float64 `json:"volume"` - } `json:"filament"` -} - -// PrintStats information from the print stats of a file. -type PrintStats struct { - // Failure number of failed prints. - Failure int `json:"failure"` - - // Success number of success prints. - Success int `json:"success"` - - // Last print information. - Last struct { - // Date of the last print. - Date JSONTime `json:"date"` - - // Success or not. - Success bool `json:"success"` - } `json:"last"` -} - -// UploadFileResponse is the response to a UploadFileRequest. -type UploadFileResponse struct { - // Abridged information regarding the file that was just uploaded. If only - // uploaded to local this will only contain the local property. If uploaded - // to SD card, this will contain both local and sdcard properties. Only - // contained if a file was uploaded, not present if only a new folder was - // created. - File struct { - // Local is the information regarding the file that was just uploaded - // to the local storage. - Local *FileResponse `json:"local"` - - // SDCard is the information regarding the file that was just uploaded - // to the printer’s SD card. - SDCard *FileResponse `json:"sdcard"` - } `json:"files"` - - // Done whether any file processing after upload has already finished or - // not, e.g. due to first needing to perform a slicing step. Clients may - // use this information to direct progress displays related to the upload. - Done bool `json:"done"` -} - -// SystemCommandsResponse is the response to a SystemCommandsRequest. -type SystemCommandsResponse struct { - Core []*CommandDefinition `json:"core"` - Custom []*CommandDefinition `json:"custom"` -} - -// CommandSource is the source of the command definition. -type CommandSource string - -const ( - // Core for system actions defined by OctoPrint itself. - Core CommandSource = "core" - - // Custom for custom system commands defined by the user through `config.yaml`. - Custom CommandSource = "custom" -) - -// CommandDefinition describe a system command. -type CommandDefinition struct { - // Name of the command to display in the System menu. - Name string `json:"name"` - - // Command is the full command line to execute for the command. - Command string `json:"command"` - - // Action is an identifier to refer to the command programmatically. The - // special `action` string divider signifies a `divider` in the menu. - Action string `json:"action"` - - // Confirm if present and set, this text will be displayed to the user in a - // confirmation dialog they have to acknowledge in order to really execute - // the command. - RawConfirm json.RawMessage `json:"confirm"` - Confirm string `json:"-"` - - // Async whether to execute the command asynchronously or wait for its - // result before responding to the HTTP execution request. - Async bool `json:"async"` - - // Ignore whether to ignore the return code of the command’s execution. - Ignore bool `json:"ignore"` - - // Source of the command definition. - Source CommandSource `json:"source"` - - // Resource is the URL of the command to use for executing it. - Resource string `json:"resource"` -} - -type JSONTime struct{ time.Time } - -func (t JSONTime) MarshalJSON() ([]byte, error) { - return []byte(strconv.FormatInt(time.Time(t.Time).Unix(), 10)), nil -} - -func (t *JSONTime) UnmarshalJSON(s []byte) (err error) { - r := strings.Replace(string(s), `"`, ``, -1) - if r == "null" { - return nil - } - - q, err := strconv.ParseInt(r, 10, 64) - if err != nil { - return err - } - - t.Time = time.Unix(q, 0) - return -} - -// CustomCommandsResponse is the response to a CustomCommandsRequest. -type CustomCommandsResponse struct { - Controls []*ControlContainer `json:"controls"` -} - -// ControlContainer describes a control container. -type ControlContainer struct { - // Name to display above the container, basically a section header. - Name string `json:"name"` - - // Gcode command - Command string `json:"command"` - - // Script that will be run on click - Script string `json:"script"` - - // Children a list of children controls or containers contained within this - // container. - Children []*ControlDefinition `json:"children"` - - // Layout to use for laying out the contained children, either from top to - // bottom (`vertical`) or from left to right (`horizontal``). Defaults to a - // vertical layout. - Layout string `json:"layout"` -} - -// ControlDefinition describe a system control. -type ControlDefinition struct { - // Name of the control, will be displayed either on the button if it’s a - // control sending a command or as a label for controls which only display - // output. - Name string `json:"name"` - - // Command a single GCODE command to send to the printer. Will be rendered - // as a button which sends the command to the printer upon click. The button - // text will be the value of the `name` attribute. Mutually exclusive with - // `commands` and `script`. The rendered button be disabled if the printer - // is currently offline or printing or alternatively if the requirements - // defined via the `enabled` attribute are not met. - Command string `json:"command"` - - // Command a list of GCODE commands to send to the printer. Will be rendered - // as a button which sends the commands to the printer upon click. The - // button text will be the value of the `name` attribute. Mutually exclusive - // with `command` and `script`. The rendered button will be disabled if the - // printer is currently offline or printing or alternatively if the - // requirements defined via the `enabled` attribute are not met. - Commands []string `json:"commands"` - - // Script is the name of a full blown GCODE script to send to the printer. - // Will be rendered as a button which sends the script to the printer upon - // click. The button text will be the value of the name attribute. Mutually - // exclusive with `command` and `commands`. The rendered button will be - // disabled if the printer is currently offline or printing or alternatively - // if the requirements defined via the `enabled`` attribute are not met. - // - // Values of input parameters will be available in the template context - // under the `parameter` variable (e.g. an input parameter speed will be - // available in the script template as parameter.speed). On top of that all - // other variables defined in the GCODE template context will be available. - Script string `json:"script"` - - // JavaScript snippet to be executed when the button rendered for `command` - // or `commands` is clicked. This allows to override the direct sending of - // the command or commands to the printer with more sophisticated behaviour. - // The JavaScript snippet is `eval`’d and processed in a context where the - // control it is part of is provided as local variable `data` and the - // `ControlViewModel` is available as self. - JavasScript string `json:"javascript"` - - // Enabled a JavaScript snippet to be executed when the button rendered for - // `command` or `commands` is clicked. This allows to override the direct - // sending of the command or commands to the printer with more sophisticated - // behaviour. The JavaScript snippet is `eval`’d and processed in a context - // where the control it is part of is provided as local variable `data` and - // the `ControlViewModel` is available as `self`. - Enabled bool `json:"enabled"` - - // Input a list of definitions of input parameters for a command or - // commands, to be rendered as additional input fields. - Input *ControlInput `json:"input"` - - // Regex a regular expression to match against lines received from the - // printer to retrieve information from it (e.g. specific output). Together - // with template this allows rendition of received data from the printer - // within the UI. - Regex string `json:"regex"` - - // Template to use for rendering the match of `regex`. May contain - // placeholders in Python Format String Syntax[1] for either named groups - // within the regex (e.g. `Temperature: {temperature}` for a regex - // `T:\s*(?P\d+(\.\d*)`) or positional groups within the regex - // (e.g. `Position: X={0}, Y={1}, Z={2}, E={3}` for a regex - // `X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:([0-9.]+)`). - // https://docs.python.org/2/library/string.html#format-string-syntax - Template string `json:"template"` - - // Confirm a text to display to the user to confirm his button press. Can - // be used with sensitive custom controls like changing EEPROM values in - // order to prevent accidental clicks. - Confirm string `json:"confirm"` -} - -// ControlInput a list of definitions of input parameters for a command or -// commands, to be rendered as additional input fields. -type ControlInput struct { - // Name to display for the input field. - Name string `json:"name"` - - // Parameter name for the input field, used as a placeholder in - // command/commands. - Parameter string `json:"parameter"` - - // Default value for the input field. - Default interface{} `json:"default"` - - // Slider if defined instead of an input field a slider control will be - // rendered. - Slider struct { - // Minimum value of the slider, defaults to 0. - Min int `json:"min"` - - // Maximum value of the slider, defaults to 255. - Maximum int `json:"max"` - - // Step size per slider “tick”, defaults to 1. - Step int `json:"step"` - } `json:"slider"` -} - -// Settings are the current configuration of OctoPrint. -type SettingsResponse struct { - // API REST API settings. - API *APIConfig `json:"api"` - - // Features settings to enable or disable OctoPrint features. - Feature *FeaturesConfig `json:"feature"` - - //Folder settings to set custom paths for folders used by OctoPrint. - Folder *FolderConfig `json:"folder"` - - // Serial settings to configure the serial connection to the printer. - Serial *SerialConfig `json:"serial"` - - // Server settings to configure the server. - Server *ServerConfig `json:"server"` - - // Temperature profiles which will be displayed in the temperature tab. - Temperature *TemperatureConfig `json:"temperature"` - - // TerminalFilters to display in the terminal tab for filtering certain - // lines from the display terminal log. - TerminalFilters []*TerminalFilter `json:"terminalFilters"` - - // Webcam settings to configure webcam support. - Webcam *WebcamConfig `json:"json"` - - // Un-handled values - Appearance interface{} `json:"appearance"` - Plugins interface{} `json:"plugins"` - Printer interface{} `json:"printer"` -} - -// APIConfig REST API settings. -type APIConfig struct { - // Enabled whether to enable the API. - Enabled bool `json:"enabled"` - - // Key current API key needed for accessing the API - Key string `json:"key"` -} - -// FeaturesConfig settings to enable or disable OctoPrint features. -type FeaturesConfig struct { - // SizeThreshold maximum size a GCODE file may have to automatically be - // loaded into the viewer, defaults to 20MB. Maps to - // gcodeViewer.sizeThreshold in config.yaml. - SizeThreshold uint64 - - // MobileSizeThreshold maximum size a GCODE file may have on mobile devices - // to automatically be loaded into the viewer, defaults to 2MB. Maps to - // gcodeViewer.mobileSizeThreshold in config.yaml. - MobileSizeThreshold uint64 `json:"mobileSizeThreshold"` - - // TemperatureGraph whether to enable the temperature graph in the UI or not. - TemperatureGraph bool `json:"temperatureGraph"` - - // WaitForStart specifies whether OctoPrint should wait for the start - // response from the printer before trying to send commands during connect. - WaitForStart bool `json:"waitForStart"` - - // AlwaysSendChecksum specifies whether OctoPrint should send linenumber + - // checksum with every printer command. Needed for successful communication - // with Repetier firmware. - AlwaysSendChecksum bool `json:"alwaysSendChecksum"` - NeverSendChecksum bool `json:"neverSendChecksum"` - - // SDSupport specifies whether support for SD printing and file management - // should be enabled - SDSupport bool `json:"sdSupport"` - - // SDAlwaysAvailable whether to always assume that an SD card is present in - // the printer. Needed by some firmwares which don't report the SD card - // status properly. - SDAlwaysAvailable bool `json:"sdAlwaysAvailable"` - - // SDReleativePath Specifies whether firmware expects relative paths for - // selecting SD files. - SDRelativePath bool `json:"sdRelativePath"` - - // SwallowOkAfterResend whether to ignore the first ok after a resend - // response. Needed for successful communication with Repetier firmware. - SwallowOkAfterResend bool `json:"swallowOkAfterResend"` - - // RepetierTargetTemp whether the printer sends repetier style target - // temperatures in the format `TargetExtr0:` instead of - // attaching that information to the regular M105 responses. - RepetierTargetTemp bool `json:"repetierTargetTemp"` - - // ExternalHeatupDetection whether to enable external heatup detection (to - // detect heatup triggered e.g. through the printer's LCD panel or while - // printing from SD) or not. Causes issues with Repetier's "first ok then - // response" approach to communication, so disable for printers running - // Repetier firmware. - ExternalHeatupDetection bool `json:"externalHeatupDetection"` - - // KeyboardControl whether to enable the keyboard control feature in the - // control tab. - KeyboardControl bool `json:"keyboardControl"` - - // PollWatched whether to actively poll the watched folder (true) or to rely - // on the OS's file system notifications instead (false). - PollWatched bool `json:"pollWatched"` - - // IgnoreIdenticalResends whether to ignore identical resends from the - // printer (true, repetier) or not (false). - IgnoreIdenticalResends bool `json:"ignoreIdenticalResends"` - - // ModelSizeDetection whether to enable model size detection and warning - // (true) or not (false) - ModelSizeDetection bool `json:"modelSizeDetection"` - - // FirmwareDetection whether to attempt to auto detect the firmware of the - // printer and adjust settings accordingly (true) or not and rely on manual - // configuration (false) - FirmwareDetection bool `json:"firmwareDetection"` - - // PrintCancelConfirmation whether to show a confirmation on print - // cancelling (true) or not (false). - PrintCancelConfirmation bool `json:"printCancelConfirmation"` - - // BlockWhileDwelling whether to block all sending to the printer while a G4 - // (dwell) command is active (true, repetier) or not (false). - BlockWhileDwelling bool `json:"blockWhileDwelling"` -} - -// FolderConfig settings to set custom paths for folders used by OctoPrint. -type FolderConfig struct { - // Uploads absolute path where to store gcode uploads. Defaults to the - // uploads folder in the OctoPrint settings folder. - Uploads string `json:"uploads"` - - // Timelapse absolute path where to store finished timelapse recordings. - // Defaults to the timelapse folder in the OctoPrint settings dir. - Timelapse string `json:"timelapse"` - - // TimelapseTmp absolute path where to store temporary timelapse files. - // Defaults to the timelapse/tmp folder in the OctoPrint settings dir Maps - // to folder.timelapse_tmp in config.yaml. - TimelapseTmp string `json:"timelapseTmp"` - - // Logs absolute path where to store log files. Defaults to the logs folder - // in the OctoPrint settings dir - Logs string `json:"logs"` - - // Watched absolute path to a folder being watched for new files which then - // get automatically added to OctoPrint (and deleted from that folder). - // Can e.g. be used to define a folder which can then be mounted from remote - // machines and used as local folder for quickly adding downloaded and/or - // sliced objects to print in the future. - Watched string `json:"watched"` -} - -// SerialConfig settings to configure the serial connection to the printer. -type SerialConfig struct { - // Port is the default serial port, defaults to unset (= AUTO) - Port string `json:"port"` - - // Baudrate is the default baudrate, defaults to unset (= AUTO) - Baudrate int `json:"baudrate"` - - // Available serial ports - PortOptions []string `json:"portOptions"` - - // Available serial baudrates - BaudrateOptions []int `json:"baudrateOptions"` - - // Autoconnect whether to automatically connect to the printer on server - // startup (if available). - Autoconnect bool `json:"autoconnect"` - - // TimeoutConnection for waiting to establish a connection with the selected - // port, in seconds. Defaults to 2 sec. Maps to serial.timeout.connection in - // config.yaml - TimeoutConnection float64 `json:"timeoutConnection"` - - // TimeoutDetection for waiting for a response from the currently tested - // port during autodetect, in seconds. Defaults to 0.5 sec Maps to - // serial.timeout.detection in config.yaml - TimeoutDetection float64 `json:"timeoutDetection"` - - // TimeoutCommunication during serial communication, in seconds. Defaults to - // 30 sec. Maps to serial.timeout.communication in config.yaml - TimeoutCommunication float64 `json:"timeoutCommunication"` - - // TimeoutTemperature after which to query temperature when no target is - // set. Maps to serial.timeout.temperature in config.yaml - TimeoutTemperature float64 `json:"timeoutTemperature"` - - // TimeoutTemperatureTargetSet after which to query temperature when a - // target is set. Maps to serial.timeout.temperatureTargetSet in config.yaml - TimeoutTemperatureTargetSet float64 `json:"timeoutTemperatureTargetSet"` - - // TimeoutSDStatus after which to query the SD status while SD printing. - // Maps to serial.timeout.sdStatus in config.yaml - TimeoutSDStatus float64 `json:"timeoutSdStatus"` - - // Log whether to log whole communication to serial.log (warning: might - // decrease performance) - Log bool `json:"log"` - - // AdditionalPorts use this to define additional patterns to consider for - // serial port listing. Must be a valid "glob" pattern (see - // http://docs.python.org/2/library/glob.html). Defaults to not set. - AdditionalPorts []string `json:"additionalPorts"` - - // AdditionalBaudrates use this to define additional baud rates to offer for - // connecting to serial ports. Must be a valid integer. Defaults to not set - AdditionalBaudrates []int `json:"additionalBaudrates"` - - // LongRunningCommands which are known to take a long time to be - // acknowledged by the firmware. E.g. homing, dwelling, auto leveling etc. - LongRunningCommands []string `json:"longRunningCommands"` - - // ChecksumRequiringCommands which need to always be send with a checksum. - // Defaults to only M110 - ChecksumRequiringCommands []string `json:"checksumRequiringCommands"` - - // HelloCommand to send in order to initiate a handshake with the printer. - // Defaults to "M110 N0" which simply resets the line numbers in the - // firmware and which should be acknowledged with a simple "ok". - HelloCommand string `json:"helloCommand"` - - // IgnoreErrorsFromFirmware whether to completely ignore errors from the - // firmware or not - IgnoreErrorsFromFirmware bool `json:"ignoreErrorsFromFirmware"` - - // DisconnectOnErrors whether to disconnect on errors or not. - DisconnectOnErrors bool `json:"disconnectOnErrors"` - - // TriggerOkForM29 whether to "manually" trigger an ok for M29 (a lot of - // versions of this command are buggy and the responds skips on the ok) - TriggerOkForM29 bool `json:"triggerOkForM29"` - - // SupportResendsWIthoutOk whether to support resends without follow-up ok - // or not. - SupportResendsWIthoutOk string `json:"supportResendsWIthoutOk"` - - // Maps to serial.maxCommunicationTimeouts.idle in config.yaml - MaxTimeoutsIdle float64 `json:"maxTimeoutsIdle"` - - // MaxTimeoutsPrinting maximum number of consecutive communication timeouts - // after which the printer will be considered dead and OctoPrint disconnects - // with an error. Maps to serial.maxCommunicationTimeouts.printing in - // config.yaml - MaxTimeoutsPrinting float64 `json:"maxTimeoutsPrinting"` - - // MaxTimeoutsPrinting maximum number of consecutive communication timeouts - // after which the printer will be considered dead and OctoPrint disconnects - // with an error. Maps to serial.maxCommunicationTimeouts.log in config.yaml - MaxTimeoutsLong float64 `json:"maxTimeoutsLong"` -} - -// ServerConfig settings to configure the server. -type ServerConfig struct { - // Commands to restart/shutdown octoprint or the system it's running on. - Commands struct { - // ServerRestartCommand to restart OctoPrint, defaults to being unset - ServerRestartCommand string `json:"serverRestartCommand"` - - //SystemRestartCommand to restart the system OctoPrint is running on, - // defaults to being unset - SystemRestartCommand string `json:"systemRestartCommand"` - - // SystemShutdownCommand Command to shut down the system OctoPrint is - // running on, defaults to being unset - SystemShutdownCommand string `json:"systemShutdownCommand"` - } `json:"commands"` - - // Diskspace settings of when to display what disk space warning - Diskspace struct { - // Warning threshold (bytes) after which to consider disk space becoming - // sparse, defaults to 500MB. - Warning uint64 `json:"warning"` - - // Critical threshold (bytes) after which to consider disk space becoming - // critical, defaults to 200MB. - Critical uint64 `json:"critical"` - } `json:"diskspace"` - // OnlineCheck configuration of the regular online connectivity check. - OnlineCheck struct { - // Enabled whether the online check is enabled, defaults to false due to - // valid privacy concerns. - Enabled bool `json:"enabled"` - - // Interval in which to check for online connectivity (in seconds) - Interval int `json:"interval"` - - // Host DNS host against which to check (default: 8.8.8.8 aka Google's DNS) - Host string `json:"host"` - - // DNS port against which to check (default: 53 - the default DNS port) - Port int `json:"port"` - } `json:"onlineCheck"` - // PluginBlacklist configuration of the plugin blacklist - PluginBlacklist struct { - // Enabled whether use of the blacklist is enabled, defaults to false - Enabled bool `json:"enabled"` - - // URL from which to fetch the blacklist - URL string `json:"url"` - - // TTL is time to live of the cached blacklist, in secs (default: 15mins) - TTL int `json:"ttl"` - } `json:"pluginBlacklist"` -} - -// TemperatureConfig temperature profiles which will be displayed in the -// temperature tab. -type TemperatureConfig struct { - // Graph cutoff in minutes. - Cutoff int `json:"cutoff"` - - // Profiles which will be displayed in the temperature tab. - TemperaturePresets []*TemperaturePreset `json:"profiles"` - - // SendAutomatically enable this to have temperature fine adjustments you - // do via the + or - button be sent to the printer automatically. - SendAutomatically bool `json:"sendAutomatically"` - - // SendAutomaticallyAfter OctoPrint will use this delay to limit the number - // of sent temperature commands should you perform multiple fine adjustments - // in a short time. - SendAutomaticallyAfter float64 `json:"sendAutomaticallyAfter"` -} - -// TerminalFilter to display in the terminal tab for filtering certain lines -// from the display terminal log. -type TerminalFilter struct { - Name string `json:"name"` - RegEx string `json:"regex"` -} - -// WebcamConfig settings to configure webcam support. -type WebcamConfig struct { - // StreamUrl use this option to enable display of a webcam stream in the - // UI, e.g. via MJPG-Streamer. Webcam support will be disabled if not - // set. Maps to webcam.stream in config.yaml. - StreamURL string `json:"streamUrl"` - - // SnapshotURL use this option to enable timelapse support via snapshot, - // e.g. via MJPG-Streamer. Timelapse support will be disabled if not set. - // Maps to webcam.snapshot in config.yaml. - SnapshotURL string `json:"snapshotUrl"` - - // FFmpegPath path to ffmpeg binary to use for creating timelapse - // recordings. Timelapse support will be disabled if not set. Maps to - // webcam.ffmpeg in config.yaml. - FFmpegPath string `json:"ffmpegPath"` - - // Bitrate to use for rendering the timelapse video. This gets directly - // passed to ffmpeg. - Bitrate int `json:"bitrate"` - - // FFmpegThreads number of how many threads to instruct ffmpeg to use for - // encoding. Defaults to 1. Should be left at 1 for RPi1. - FFmpegThreads int `json:"ffmpegThreads"` - - // Watermark whether to include a "created with OctoPrint" watermark in the - // generated timelapse movies. - Watermark string `json:"watermark"` - - // FlipH whether to flip the webcam horizontally. - FlipH bool `json:"flipH"` - - // FlipV whether to flip the webcam vertically. - FlipV bool `json:"flipV"` - - // Rotate90 whether to rotate the webcam 90° counter clockwise. - Rotate90 bool `json:"rotate90"` -} - - - - -// TemperaturePreset describes the temperature preset for a given material. -type TemperaturePreset struct { - Name string `json:"name"` - Bed float64 `json:"bed"` - Extruder float64 `json:"extruder"` -} - - - - -type PrinterProfilesResponse struct { - Profiles []*PrinterProfile `json:"profiles"` -} - -type PrinterProfile struct { - Id string `json:"id"` - Name string `json:"name"` - - Volume struct { - FormFactor string `json:"formFactor"` - Origin string `json:"origin"` - Width float64 `json:"width"` - Depth float64 `json:"depth"` - Height float64 `json:"height"` - } `json:"volume"` - - Extruder struct { - Count int `json:"count"` - SharedNozzle bool `json:"sharedNozzle"` - } `json:"extruder"` -} diff --git a/octoprintApis/common_test.go b/octoprintApis/common_test.go old mode 100644 new mode 100755 index 28c4151c..1db0f71a --- a/octoprintApis/common_test.go +++ b/octoprintApis/common_test.go @@ -1,5 +1,6 @@ package octoprintApis +/* import ( "encoding/json" "testing" @@ -169,8 +170,9 @@ func TestFileInformation_IsFolder(t *testing.T) { assert.False(t, f.IsFolder()) } -func TestJSONTime_UnmarshalJSONWithNull(t *testing.T) { - time := &JSONTime{} +func TestJsonTime_UnmarshalJsonWithNull(t *testing.T) { + time := &JsonTime{} err := time.UnmarshalJSON([]byte("null")) assert.NoError(t, err) } +*/ \ No newline at end of file diff --git a/octoprintApis/connection.go b/octoprintApis/connection.go index c85a4ccf..55c1bb39 100755 --- a/octoprintApis/connection.go +++ b/octoprintApis/connection.go @@ -1,112 +1,17 @@ package octoprintApis import ( - "bytes" - "encoding/json" - "io" -) - -const URIConnection = "/api/connection" - -var ConnectionErrors = StatusMapping{ - 400: "The selected port or baudrate for a connect command are not part of the available option", -} - -// ConnectionRequest Retrieve the current connection settings, including -// information regarding the available baudrates and serial ports and the -// current connection state. -type ConnectionRequest struct{} - -// Do sends an API request and returns the API response. -func (cmd *ConnectionRequest) Do(c *Client) (*ConnectionResponse, error) { - b, err := c.doJSONRequest("GET", URIConnection, nil, nil) - if err != nil { - return nil, err - } - - r := &ConnectionResponse{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - - return r, err -} - -// ConnectRequest sets the given target temperature on the printer’s tools. -type ConnectRequest struct { - // Port specific port to connect to. If not set the current `portPreference` - // will be used, or if no preference is available auto detection will be - // attempted. - Port string `json:"port,omitempty"` - // BaudRate specific baudrate to connect with. If not set the current - // `baudratePreference` will be used, or if no preference is available auto - // detection will be attempted. - BaudRate int `json:"baudrate,omitempty"` - // PrinterProfile specific printer profile to use for connection. If not set - // the current default printer profile will be used. - PrinterProfile string `json:"printerProfile,omitempty"` - // Save whether to save the request’s port and baudrate settings as new - // preferences. - Save bool `json:"save"` - // Autoconnect whether to automatically connect to the printer on - // OctoPrint’s startup in the future. - Autoconnect bool `json:"autoconnect"` -} + // "bytes" + // "encoding/json" + // "io" -// Do sends an API request and returns an error if any. -func (cmd *ConnectRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) - return err -} - -func (cmd *ConnectRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ConnectRequest - }{ - Command: "connect", - ConnectRequest: *cmd, - }) -} - -// DisconnectRequest instructs OctoPrint to disconnect from the printer. -type DisconnectRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *DisconnectRequest) Do(c *Client) error { - payload := map[string]string{"command": "disconnect"} - - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(payload); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) - return err -} + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) -// FakesACKRequest fakes an acknowledgment message for OctoPrint in case one got -// lost on the serial line and the communication with the printer since stalled. -// -// This should only be used in “emergencies” (e.g. to save prints), the reason -// for the lost acknowledgment should always be properly investigated and -// removed instead of depending on this “symptom solver”. -type FakesACKRequest struct{} -// Do sends an API request and returns an error if any. -func (cmd *FakesACKRequest) Do(c *Client) error { - payload := map[string]string{"command": "fake_ack"} +const ConnectionApiUri = "/api/connection" - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(payload); err != nil { - return err - } - _, err := c.doJSONRequest("POST", URIConnection, b, ConnectionErrors) - return err +var ConnectionErrors = StatusMapping { + 400: "The selected port or baudrate for a connect command are not part of the available option", } diff --git a/octoprintApis/dataModels/ApiConfig.go b/octoprintApis/dataModels/ApiConfig.go new file mode 100755 index 00000000..e2055311 --- /dev/null +++ b/octoprintApis/dataModels/ApiConfig.go @@ -0,0 +1,11 @@ +package dataModels + + +// APIConfig REST API settings. +type APIConfig struct { + // Enabled whether to enable the API. + IsEnabled bool `json:"enabled"` + + // Key current API key needed for accessing the API + Key string `json:"key"` +} diff --git a/octoprintApis/dataModels/Axis.go b/octoprintApis/dataModels/Axis.go new file mode 100755 index 00000000..55d48c01 --- /dev/null +++ b/octoprintApis/dataModels/Axis.go @@ -0,0 +1,10 @@ +package dataModels + + +type Axis string + +const ( + XAxis Axis = "x" + YAxis Axis = "y" + ZAxis Axis = "z" +) diff --git a/octoprintApis/dataModels/CommandDefinition.go b/octoprintApis/dataModels/CommandDefinition.go new file mode 100755 index 00000000..07aa5f7f --- /dev/null +++ b/octoprintApis/dataModels/CommandDefinition.go @@ -0,0 +1,38 @@ +package dataModels + +import ( + "encoding/json" +) + + +// CommandDefinition describe a system command. +type CommandDefinition struct { + // Name of the command to display in the System menu. + Name string `json:"name"` + + // Command is the full command line to execute for the command. + Command string `json:"command"` + + // Action is an identifier to refer to the command programmatically. The + // special `action` string divider signifies a `divider` in the menu. + Action string `json:"action"` + + // Confirm if present and set, this text will be displayed to the user in a + // confirmation dialog they have to acknowledge in order to really execute + // the command. + RawConfirm json.RawMessage `json:"confirm"` + Confirm string `json:"-"` + + // Async whether to execute the command asynchronously or wait for its + // result before responding to the HTTP execution request. + IsAsync bool `json:"async"` + + // Ignore whether to ignore the return code of the command’s execution. + Ignore bool `json:"ignore"` + + // Source of the command definition. + Source CommandSource `json:"source"` + + // Resource is the URL of the command to use for executing it. + Resource string `json:"resource"` +} diff --git a/octoprintApis/dataModels/CommandSource.go b/octoprintApis/dataModels/CommandSource.go new file mode 100755 index 00000000..91d197b4 --- /dev/null +++ b/octoprintApis/dataModels/CommandSource.go @@ -0,0 +1,13 @@ +package dataModels + + +// CommandSource is the source of the command definition. +type CommandSource string + +const ( + // Core for system actions defined by OctoPrint itself. + Core CommandSource = "core" + + // Custom for custom system commands defined by the user through `config.yaml`. + Custom CommandSource = "custom" +) diff --git a/octoprintApis/dataModels/ConnectionResponse.go b/octoprintApis/dataModels/ConnectionResponse.go new file mode 100755 index 00000000..4fe7a83b --- /dev/null +++ b/octoprintApis/dataModels/ConnectionResponse.go @@ -0,0 +1,43 @@ +package dataModels + + +// ConnectionResponse is the response from a connection command. +type ConnectionResponse struct { + Current struct { + // State current state of the connection. + State ConnectionState `json:"state"` + + // Port to connect to. + Port string `json:"port"` + + // BaudRate speed of the connection. + BaudRate int `json:"baudrate"` + + // PrinterProfile profile to use for connection. + PrinterProfile string `json:"printerProfile"` + } + + Options struct { + // Ports list of available ports. + Ports []string `json:"ports"` + + // BaudRates list of available speeds. + BaudRates []int `json:"baudrates"` + + // PrinterProfile list of available profiles. + PrinterProfiles []*Profile `json:"printerProfiles"` + + // PortPreference default port. + PortPreference string `json:"portPreference"` + + // BaudRatePreference default speed. + BaudRatePreference int `json:"baudratePreference"` + + // PrinterProfilePreference default profile. + PrinterProfilePreference string `json:"printerProfilePreference"` + + // Autoconnect whether to automatically connect to the printer on + // OctoPrint’s startup in the future. + Autoconnect bool `json:"autoconnect"` + } +} diff --git a/octoprintApis/dataModels/ConnectionState.go b/octoprintApis/dataModels/ConnectionState.go new file mode 100755 index 00000000..f2d94a8d --- /dev/null +++ b/octoprintApis/dataModels/ConnectionState.go @@ -0,0 +1,45 @@ +package dataModels + +import ( + "strings" +) + + +type ConnectionState string + +const ( + Operational ConnectionState = "Operational" +) + +// The states are based on: +// https://github.com/foosel/OctoPrint/blob/77753ca02602d3a798d6b0a22535e6fd69ff448a/src/octoprint/util/comm.py#L549 + +func (s ConnectionState) IsOperational() bool { + return strings.HasPrefix(string(s), "Operational") +} + +func (s ConnectionState) IsPrinting() bool { + return strings.HasPrefix(string(s), "Printing") || + strings.HasPrefix(string(s), "Starting") || + strings.HasPrefix(string(s), "Sending") || + strings.HasPrefix(string(s), "Paused") || + strings.HasPrefix(string(s), "Pausing") || + strings.HasPrefix(string(s), "Transfering") +} + +func (s ConnectionState) IsOffline() bool { + return strings.HasPrefix(string(s), "Offline") || + strings.HasPrefix(string(s), "Closed") +} + +func (s ConnectionState) IsError() bool { + return strings.HasPrefix(string(s), "Error") || + strings.HasPrefix(string(s), "Unknown") +} + +func (s ConnectionState) IsConnecting() bool { + return strings.HasPrefix(string(s), "Opening") || + strings.HasPrefix(string(s), "Detecting") || + strings.HasPrefix(string(s), "Connecting") || + strings.HasPrefix(string(s), "Detecting") +} diff --git a/octoprintApis/dataModels/ControlContainer.go b/octoprintApis/dataModels/ControlContainer.go new file mode 100755 index 00000000..0a968a98 --- /dev/null +++ b/octoprintApis/dataModels/ControlContainer.go @@ -0,0 +1,23 @@ +package dataModels + + +// ControlContainer describes a control container. +type ControlContainer struct { + // Name to display above the container, basically a section header. + Name string `json:"name"` + + // Gcode command + Command string `json:"command"` + + // Script that will be run on click + Script string `json:"script"` + + // Children a list of children controls or containers contained within this + // container. + Children []*ControlDefinition `json:"children"` + + // Layout to use for laying out the contained children, either from top to + // bottom (`vertical`) or from left to right (`horizontal``). Defaults to a + // vertical layout. + Layout string `json:"layout"` +} diff --git a/octoprintApis/dataModels/ControlDefinition.go b/octoprintApis/dataModels/ControlDefinition.go new file mode 100755 index 00000000..e0673321 --- /dev/null +++ b/octoprintApis/dataModels/ControlDefinition.go @@ -0,0 +1,79 @@ +package dataModels + + +// ControlDefinition describe a system control. +type ControlDefinition struct { + // Name of the control, will be displayed either on the button if it’s a + // control sending a command or as a label for controls which only display + // output. + Name string `json:"name"` + + // Command a single GCODE command to send to the printer. Will be rendered + // as a button which sends the command to the printer upon click. The button + // text will be the value of the `name` attribute. Mutually exclusive with + // `commands` and `script`. The rendered button be disabled if the printer + // is currently offline or printing or alternatively if the requirements + // defined via the `enabled` attribute are not met. + Command string `json:"command"` + + // Command a list of GCODE commands to send to the printer. Will be rendered + // as a button which sends the commands to the printer upon click. The + // button text will be the value of the `name` attribute. Mutually exclusive + // with `command` and `script`. The rendered button will be disabled if the + // printer is currently offline or printing or alternatively if the + // requirements defined via the `enabled` attribute are not met. + Commands []string `json:"commands"` + + // Script is the name of a full blown GCODE script to send to the printer. + // Will be rendered as a button which sends the script to the printer upon + // click. The button text will be the value of the name attribute. Mutually + // exclusive with `command` and `commands`. The rendered button will be + // disabled if the printer is currently offline or printing or alternatively + // if the requirements defined via the `enabled`` attribute are not met. + // + // Values of input parameters will be available in the template context + // under the `parameter` variable (e.g. an input parameter speed will be + // available in the script template as parameter.speed). On top of that all + // other variables defined in the GCODE template context will be available. + Script string `json:"script"` + + // JavaScript snippet to be executed when the button rendered for `command` + // or `commands` is clicked. This allows to override the direct sending of + // the command or commands to the printer with more sophisticated behavior. + // The JavaScript snippet is `eval`’d and processed in a context where the + // control it is part of is provided as local variable `data` and the + // `ControlViewModel` is available as self. + JavasScript string `json:"javascript"` + + // Enabled a JavaScript snippet to be executed when the button rendered for + // `command` or `commands` is clicked. This allows to override the direct + // sending of the command or commands to the printer with more sophisticated + // behavior. The JavaScript snippet is `eval`’d and processed in a context + // where the control it is part of is provided as local variable `data` and + // the `ControlViewModel` is available as `self`. + IsEnabled bool `json:"enabled"` + + // Input a list of definitions of input parameters for a command or + // commands, to be rendered as additional input fields. + Input *ControlInput `json:"input"` + + // Regex a regular expression to match against lines received from the + // printer to retrieve information from it (e.g. specific output). Together + // with template this allows rendition of received data from the printer + // within the UI. + Regex string `json:"regex"` + + // Template to use for rendering the match of `regex`. May contain + // placeholders in Python Format String Syntax[1] for either named groups + // within the regex (e.g. `Temperature: {temperature}` for a regex + // `T:\s*(?P\d+(\.\d*)`) or positional groups within the regex + // (e.g. `Position: X={0}, Y={1}, Z={2}, E={3}` for a regex + // `X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:([0-9.]+)`). + // https://docs.python.org/2/library/string.html#format-string-syntax + Template string `json:"template"` + + // Confirm a text to display to the user to confirm his button press. Can + // be used with sensitive custom controls like changing EEPROM values in + // order to prevent accidental clicks. + Confirm string `json:"confirm"` +} diff --git a/octoprintApis/dataModels/ControlInput.go b/octoprintApis/dataModels/ControlInput.go new file mode 100755 index 00000000..9d03a78a --- /dev/null +++ b/octoprintApis/dataModels/ControlInput.go @@ -0,0 +1,29 @@ +package dataModels + + +// ControlInput a list of definitions of input parameters for a command or +// commands, to be rendered as additional input fields. +type ControlInput struct { + // Name to display for the input field. + Name string `json:"name"` + + // Parameter name for the input field, used as a placeholder in + // command/commands. + Parameter string `json:"parameter"` + + // Default value for the input field. + Default interface{} `json:"default"` + + // Slider if defined instead of an input field a slider control will be + // rendered. + Slider struct { + // Minimum value of the slider, defaults to 0. + Min int `json:"min"` + + // Maximum value of the slider, defaults to 255. + Maximum int `json:"max"` + + // Step size per slider “tick”, defaults to 1. + Step int `json:"step"` + } `json:"slider"` +} diff --git a/octoprintApis/dataModels/CustomCommandsResponse.go b/octoprintApis/dataModels/CustomCommandsResponse.go new file mode 100755 index 00000000..76e1553e --- /dev/null +++ b/octoprintApis/dataModels/CustomCommandsResponse.go @@ -0,0 +1,7 @@ +package dataModels + + +// CustomCommandsResponse is the response to a CustomCommandsRequest. +type CustomCommandsResponse struct { + Controls []*ControlContainer `json:"controls"` +} diff --git a/octoprintApis/dataModels/FeaturesConfig.go b/octoprintApis/dataModels/FeaturesConfig.go new file mode 100755 index 00000000..a39515b7 --- /dev/null +++ b/octoprintApis/dataModels/FeaturesConfig.go @@ -0,0 +1,86 @@ +package dataModels + + +// FeaturesConfig settings to enable or disable OctoPrint features. +type FeaturesConfig struct { + // SizeThreshold maximum size a GCODE file may have to automatically be + // loaded into the viewer, defaults to 20MB. Maps to + // gcodeViewer.sizeThreshold in config.yaml. + SizeThreshold uint64 + + // MobileSizeThreshold maximum size a GCODE file may have on mobile devices + // to automatically be loaded into the viewer, defaults to 2MB. Maps to + // gcodeViewer.mobileSizeThreshold in config.yaml. + MobileSizeThreshold uint64 `json:"mobileSizeThreshold"` + + // TemperatureGraph whether to enable the temperature graph in the UI or not. + TemperatureGraph bool `json:"temperatureGraph"` + + // WaitForStart specifies whether OctoPrint should wait for the start + // response from the printer before trying to send commands during connect. + WaitForStart bool `json:"waitForStart"` + + // AlwaysSendChecksum specifies whether OctoPrint should send linenumber + + // checksum with every printer command. Needed for successful communication + // with Repetier firmware. + AlwaysSendChecksum bool `json:"alwaysSendChecksum"` + NeverSendChecksum bool `json:"neverSendChecksum"` + + // SDSupport specifies whether support for SD printing and file management + // should be enabled + SdSupport bool `json:"sdSupport"` + + // SDAlwaysAvailable whether to always assume that an SD card is present in + // the printer. Needed by some firmwares which don't report the SD card + // status properly. + SdAlwaysAvailable bool `json:"sdAlwaysAvailable"` + + // SDReleativePath Specifies whether firmware expects relative paths for + // selecting SD files. + SdRelativePath bool `json:"sdRelativePath"` + + // SwallowOkAfterResend whether to ignore the first ok after a resend + // response. Needed for successful communication with Repetier firmware. + SwallowOkAfterResend bool `json:"swallowOkAfterResend"` + + // RepetierTargetTemp whether the printer sends repetier style target + // temperatures in the format `TargetExtr0:` instead of + // attaching that information to the regular M105 responses. + RepetierTargetTemp bool `json:"repetierTargetTemp"` + + // ExternalHeatupDetection whether to enable external heatup detection (to + // detect heatup triggered e.g. through the printer's LCD panel or while + // printing from SD) or not. Causes issues with Repetier's "first ok then + // response" approach to communication, so disable for printers running + // Repetier firmware. + ExternalHeatupDetection bool `json:"externalHeatupDetection"` + + // KeyboardControl whether to enable the keyboard control feature in the + // control tab. + KeyboardControl bool `json:"keyboardControl"` + + // PollWatched whether to actively poll the watched folder (true) or to rely + // on the OS's file system notifications instead (false). + PollWatched bool `json:"pollWatched"` + + // IgnoreIdenticalResends whether to ignore identical resends from the + // printer (true, repetier) or not (false). + IgnoreIdenticalResends bool `json:"ignoreIdenticalResends"` + + // ModelSizeDetection whether to enable model size detection and warning + // (true) or not (false) + ModelSizeDetection bool `json:"modelSizeDetection"` + + // FirmwareDetection whether to attempt to auto detect the firmware of the + // printer and adjust settings accordingly (true) or not and rely on manual + // configuration (false) + FirmwareDetection bool `json:"firmwareDetection"` + + // PrintCancelConfirmation whether to show a confirmation on print + // cancelling (true) or not (false). + PrintCancelConfirmation bool `json:"printCancelConfirmation"` + + // BlockWhileDwelling whether to block all sending to the printer while a G4 + // (dwell) command is active (true, repetier) or not (false). + BlockWhileDwelling bool `json:"blockWhileDwelling"` +} diff --git a/octoprintApis/dataModels/Filament.go b/octoprintApis/dataModels/Filament.go new file mode 100755 index 00000000..359e743c --- /dev/null +++ b/octoprintApis/dataModels/Filament.go @@ -0,0 +1,10 @@ +package dataModels + + +type Filament struct { + // Length estimated of filament used, in mm + Length uint32 `json:"length"` + + // Volume estimated of filament used, in cm³ + Volume float64 `json:"volume"` +} diff --git a/octoprintApis/dataModels/FileResponse.go b/octoprintApis/dataModels/FileResponse.go new file mode 100755 index 00000000..dff3d3d1 --- /dev/null +++ b/octoprintApis/dataModels/FileResponse.go @@ -0,0 +1,90 @@ +package dataModels + +import ( + // "encoding/json" + // "fmt" + // "log" + // "strconv" + // "strings" + // "time" +) + +// FileResponse contains information regarding a file. +// https://docs.octoprint.org/en/master/api/datamodel.html#file-information +type FileResponse struct { + // Name is name of the file without path. E.g. “file.gco” for a file + // “file.gco” located anywhere in the file system. + Name string `json:"name"` + + // The name of the file without the path. + Display string `json:"display"` + + // Path is the path to the file within the location. E.g. + //“folder/subfolder/file.gco” for a file “file.gco” located within “folder” + // and “subfolder” relative to the root of the location. + Path string `json:"path"` + + // Type of file. model or machinecode. Or folder if it’s a folder, in + // which case the children node will be populated. + Type string `json:"type"` + + // TypePath path to type of file in extension tree. E.g. `["model", "stl"]` + // for .stl files, or `["machinecode", "gcode"]` for .gcode files. + // `["folder"]` for folders. + TypePath []string `json:"typePath"` + + + + + // Additional properties depend on type. For a type value of folder, see Folders. For any other value see Files. + + // * Folders + // --children + // --size + + + + // * Files + // Hash is the MD5 hash of the file. Only available for `local` files. + Hash string `json:"hash"` + + // Size of the file in bytes. Only available for `local` files or `sdcard` + // files if the printer supports file sizes for sd card files. + Size uint64 `json:"size"` + + // Date when this file was uploaded. Only available for `local` files. + Date JsonTime `json:"date"` + + // Origin of the file, `local` when stored in OctoPrint’s `uploads` folder, + // `sdcard` when stored on the printer’s SD card (if available). + Origin string `json:"origin"` + + // Refs references relevant to this file, left out in abridged version. + Refs Reference `json:"refs"` + + // GCodeAnalysis information from the analysis of the GCODE file, if + // available. Left out in abridged version. + GCodeAnalysis GCodeAnalysisInformation `json:"gcodeAnalysis"` + + + + + // * Additional properties not listed in the SDK... + + // Print information from the print stats of a file. + Print PrintStats `json:"print"` + + + // Relative path to the preview thumbnail image (if it exists) + // The PrusaSlicer Thumbnails plug-in is required or this. + Thumbnail string `json:"thumbnail"` +} + +// IsFolder it returns true if the file is a folder. +func (response *FileResponse) IsFolder() bool { + if len(response.TypePath) == 1 && response.TypePath[0] == "folder" { + return true + } + + return false +} diff --git a/octoprintApis/dataModels/FilesResponse.go b/octoprintApis/dataModels/FilesResponse.go new file mode 100755 index 00000000..aa88a5e7 --- /dev/null +++ b/octoprintApis/dataModels/FilesResponse.go @@ -0,0 +1,16 @@ +package dataModels + + +// FilesResponse is the response to a FilesRequest. +type FilesResponse struct { + // Files is the list of requested files. Might be an empty list if no files are available + Files []*FileResponse + + // + Children []*FileResponse + + // Free is the amount of disk space in bytes available in the local disk + // space (refers to OctoPrint’s `uploads` folder). Only returned if file + // list was requested for origin `local` or all origins. + Free uint64 +} diff --git a/octoprintApis/dataModels/FolderConfig.go b/octoprintApis/dataModels/FolderConfig.go new file mode 100755 index 00000000..447b5f26 --- /dev/null +++ b/octoprintApis/dataModels/FolderConfig.go @@ -0,0 +1,29 @@ +package dataModels + + +// FolderConfig settings to set custom paths for folders used by OctoPrint. +type FolderConfig struct { + // Uploads absolute path where to store gcode uploads. Defaults to the + // uploads folder in the OctoPrint settings folder. + Uploads string `json:"uploads"` + + // Timelapse absolute path where to store finished timelapse recordings. + // Defaults to the timelapse folder in the OctoPrint settings dir. + Timelapse string `json:"timelapse"` + + // TimelapseTmp absolute path where to store temporary timelapse files. + // Defaults to the timelapse/tmp folder in the OctoPrint settings dir Maps + // to folder.timelapse_tmp in config.yaml. + TimelapseTmp string `json:"timelapseTmp"` + + // Logs absolute path where to store log files. Defaults to the logs folder + // in the OctoPrint settings dir + Logs string `json:"logs"` + + // Watched absolute path to a folder being watched for new files which then + // get automatically added to OctoPrint (and deleted from that folder). + // Can e.g. be used to define a folder which can then be mounted from remote + // machines and used as local folder for quickly adding downloaded and/or + // sliced objects to print in the future. + Watched string `json:"watched"` +} diff --git a/octoprintApis/dataModels/FullStateResponse.go b/octoprintApis/dataModels/FullStateResponse.go new file mode 100755 index 00000000..ee161f87 --- /dev/null +++ b/octoprintApis/dataModels/FullStateResponse.go @@ -0,0 +1,13 @@ +package dataModels + +// FullStateResponse contains informantion about the current state of the printer. +type FullStateResponse struct { + // TemperatureStateResponse is the printer’s temperature state data. + Temperature TemperatureStateResponse `json:"temperature"` + + // SD is the printer’s sd state data. + SD SdState `json:"sd"` + + // State is the printer’s general state. + State PrinterState `json:"state"` +} diff --git a/octoprintApis/dataModels/GCodeAnalysisInformation.go b/octoprintApis/dataModels/GCodeAnalysisInformation.go new file mode 100755 index 00000000..55129272 --- /dev/null +++ b/octoprintApis/dataModels/GCodeAnalysisInformation.go @@ -0,0 +1,10 @@ +package dataModels + +// GCodeAnalysisInformation Information from the analysis of the GCODE file. +type GCodeAnalysisInformation struct { + // EstimatedPrintTime is the estimated print time of the file, in seconds. + EstimatedPrintTime float64 `json:"estimatedPrintTime"` + + // Filament estimated usage of filament + Filament Filament `json:"filament"` +} diff --git a/octoprintApis/dataModels/HistoricTemperatureData.go b/octoprintApis/dataModels/HistoricTemperatureData.go new file mode 100755 index 00000000..7bc87e36 --- /dev/null +++ b/octoprintApis/dataModels/HistoricTemperatureData.go @@ -0,0 +1,38 @@ +package dataModels + +import ( + "encoding/json" +) + +// HistoricTemperatureData is temperature historic stats for a tool. +type HistoricTemperatureData historicTemperatureData + +type historicTemperatureData struct { + // Time of this data point. + Time JsonTime `json:"time"` + + // Tools is temperature stats a set of tools. + Tools map[string]TemperatureData `json:"tools"` +} + +func (h *HistoricTemperatureData) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + + ts := raw["time"] + delete(raw, "time") + b, _ = json.Marshal(map[string]interface{}{ + "time": ts, + "tools": raw, + }) + + i := &historicTemperatureData{} + if err := json.Unmarshal(b, i); err != nil { + return err + } + + *h = HistoricTemperatureData(*i) + return nil +} diff --git a/octoprintApis/JobInformation.go b/octoprintApis/dataModels/JobInformation.go similarity index 97% rename from octoprintApis/JobInformation.go rename to octoprintApis/dataModels/JobInformation.go index 3b3ec892..ff067c14 100755 --- a/octoprintApis/JobInformation.go +++ b/octoprintApis/dataModels/JobInformation.go @@ -1,4 +1,4 @@ -package octoprintApis +package dataModels import ( // "encoding/json" @@ -7,6 +7,7 @@ import ( // "time" ) + // Job information // https://docs.octoprint.org/en/master/api/datamodel.html#job-information diff --git a/octoprintApis/dataModels/JobResponse.go b/octoprintApis/dataModels/JobResponse.go new file mode 100755 index 00000000..2e7e6af4 --- /dev/null +++ b/octoprintApis/dataModels/JobResponse.go @@ -0,0 +1,19 @@ +package dataModels + +// Job information response +// https://docs.octoprint.org/en/master/api/job.html#job-information-response + +// Job information response +// https://docs.octoprint.org/en/master/api/job.html#job-information-response + +// JobResponse is the response from a job command. +type JobResponse struct { + // Job contains information regarding the target of the current print job. + Job JobInformation `json:"job"` + + // Progress contains information regarding the progress of the current job. + Progress ProgressInformation `json:"progress"` + + //State StateInformation `json:"state"` + State string `json:"state"` +} diff --git a/octoprintApis/dataModels/JsonTime.go b/octoprintApis/dataModels/JsonTime.go new file mode 100755 index 00000000..c92b169b --- /dev/null +++ b/octoprintApis/dataModels/JsonTime.go @@ -0,0 +1,29 @@ +package dataModels + +import ( + // "encoding/json" + "strconv" + "strings" + "time" +) + +type JsonTime struct{ time.Time } + +func (t JsonTime) MarshalJSON() ([]byte, error) { + return []byte(strconv.FormatInt(time.Time(t.Time).Unix(), 10)), nil +} + +func (t *JsonTime) UnmarshalJSON(s []byte) (err error) { + r := strings.Replace(string(s), `"`, ``, -1) + if r == "null" { + return nil + } + + q, err := strconv.ParseInt(r, 10, 64) + if err != nil { + return err + } + + t.Time = time.Unix(q, 0) + return +} diff --git a/octoprintApis/dataModels/Location.go b/octoprintApis/dataModels/Location.go new file mode 100755 index 00000000..262960b0 --- /dev/null +++ b/octoprintApis/dataModels/Location.go @@ -0,0 +1,10 @@ +package dataModels + +type Location string + +const ( + // URIFiles = "/api/files" + + Local Location = "local" + SDCard Location = "sdcard" +) diff --git a/octoprintApis/dataModels/MenuItem.go b/octoprintApis/dataModels/MenuItem.go new file mode 100755 index 00000000..d7d24f67 --- /dev/null +++ b/octoprintApis/dataModels/MenuItem.go @@ -0,0 +1,9 @@ +package dataModels + + +type MenuItem struct { + Name string `json:"name"` + Icon string `json:"icon"` + Panel string `json:"panel"` + Items []MenuItem `json:"items"` +} diff --git a/octoprintApis/dataModels/NotificationResponse.go b/octoprintApis/dataModels/NotificationResponse.go new file mode 100755 index 00000000..ecb64fa3 --- /dev/null +++ b/octoprintApis/dataModels/NotificationResponse.go @@ -0,0 +1,7 @@ +package dataModels + + +type NotificationResponse struct { + // Job contains information regarding the target of the current print job. + Message string `json:"message"` +} diff --git a/octoprintApis/dataModels/OctoScreenSettingsResponse.go b/octoprintApis/dataModels/OctoScreenSettingsResponse.go new file mode 100755 index 00000000..08842a4e --- /dev/null +++ b/octoprintApis/dataModels/OctoScreenSettingsResponse.go @@ -0,0 +1,16 @@ +package dataModels + + +type OctoScreenSettingsResponse struct { + // Job contains information regarding the target of the current print job. + FilamentInLength float64 `json:"filament_in_length"` + FilamentOutLength float64 `json:"filament_out_length"` + ToolChanger bool `json:"toolchanger"` + XAxisInverted bool `json:"x_axis_inverted"` + YAxisInverted bool `json:"y_axis_inverted"` + ZAxisInverted bool `json:"z_axis_inverted"` + MenuStructure []MenuItem `json:"menu_structure"` + GCodes struct { + AutoBedLevel string `json:"auto_bed_level"` + } `json:"gcodes"` +} diff --git a/octoprintApis/dataModels/PauseAction.go b/octoprintApis/dataModels/PauseAction.go new file mode 100755 index 00000000..66ae4470 --- /dev/null +++ b/octoprintApis/dataModels/PauseAction.go @@ -0,0 +1,15 @@ +package dataModels + +type PauseAction string + +const ( + // Pause the current job if it’s printing, does nothing if it’s already paused. + Pause PauseAction = "pause" + + // Resume the current job if it’s paused, does nothing if it’s printing. + Resume PauseAction = "resume" + + // Toggle the pause state of the job, pausing it if it’s printing and + // resuming it if it’s currently paused. + Toggle PauseAction = "toggle" +) diff --git a/octoprintApis/dataModels/Plugin.go b/octoprintApis/dataModels/Plugin.go new file mode 100755 index 00000000..316020c2 --- /dev/null +++ b/octoprintApis/dataModels/Plugin.go @@ -0,0 +1,28 @@ +package dataModels + + +// Plugin - +type Plugin struct { + Author string `json:"author"` + IsBlacklisted bool `json:"blacklisted"` + Bundled bool `json:"bundled"` + Description string `json:"description"` + // DisablingDiscouraged bool `json:"disabling_discouraged"` + IsEnabled bool `json:"enabled"` + ForcedDisabled bool `json:"forced_disabled"` + Incompatible bool `json:"incompatible"` + Key string `json:"key"` + License string `json:"license"` + IsManagable bool `json:"managable"` + Name string `json:"name"` + // notifications: [] + Origin string `json:"origin"` + PendingDisable bool `json:"pending_disable"` + PendingEnable bool `json:"pending_enable"` + PendingInstall bool `json:"pending_install"` + PendingUninstall bool `json:"pending_uninstall"` + Python string `json:"python"` + SafeModeVictim bool `json:"safe_mode_victim"` + URL string `json:"url"` + Version string `json:"version"` +} diff --git a/octoprintApis/dataModels/PluginManagerInfoResponse.go b/octoprintApis/dataModels/PluginManagerInfoResponse.go new file mode 100755 index 00000000..be950f46 --- /dev/null +++ b/octoprintApis/dataModels/PluginManagerInfoResponse.go @@ -0,0 +1,12 @@ +package dataModels + + +// PluginManagerInfoResponse - +type PluginManagerInfoResponse struct { + Octoprint string `json:"octoprint"` + IsOnline bool `json:"online"` + //orphan_data: { } + OS string `json:"os"` + //pip: {} + Plugins []Plugin `json:"plugins"` +} diff --git a/octoprintApis/dataModels/PrintStats.go b/octoprintApis/dataModels/PrintStats.go new file mode 100755 index 00000000..2e08b8ee --- /dev/null +++ b/octoprintApis/dataModels/PrintStats.go @@ -0,0 +1,20 @@ +package dataModels + + +// PrintStats information from the print stats of a file. +type PrintStats struct { + // Failure number of failed prints. + Failure int `json:"failure"` + + // Success number of success prints. + SuccessfullPrintCount int `json:"success"` + + // Last print information. + Last struct { + // Date of the last print. + Date JsonTime `json:"date"` + + // Success or not. + IsSuccess bool `json:"success"` + } `json:"last"` +} diff --git a/octoprintApis/dataModels/PrinterProfileResponse.go b/octoprintApis/dataModels/PrinterProfileResponse.go new file mode 100755 index 00000000..337c8928 --- /dev/null +++ b/octoprintApis/dataModels/PrinterProfileResponse.go @@ -0,0 +1,20 @@ +package dataModels + + +type PrinterProfileResponse struct { + Id string `json:"id"` + Name string `json:"name"` + + Volume struct { + FormFactor string `json:"formFactor"` + Origin string `json:"origin"` + Width float64 `json:"width"` + Depth float64 `json:"depth"` + Height float64 `json:"height"` + } `json:"volume"` + + Extruder struct { + Count int `json:"count"` + HasSharedNozzle bool `json:"sharedNozzle"` + } `json:"extruder"` +} diff --git a/octoprintApis/dataModels/PrinterProfilesResponse.go b/octoprintApis/dataModels/PrinterProfilesResponse.go new file mode 100755 index 00000000..79f1b7fd --- /dev/null +++ b/octoprintApis/dataModels/PrinterProfilesResponse.go @@ -0,0 +1,6 @@ +package dataModels + + +type PrinterProfilesResponse struct { + Profiles []*PrinterProfileResponse `json:"profiles"` +} diff --git a/octoprintApis/dataModels/PrinterState.go b/octoprintApis/dataModels/PrinterState.go new file mode 100755 index 00000000..915d7959 --- /dev/null +++ b/octoprintApis/dataModels/PrinterState.go @@ -0,0 +1,16 @@ +package dataModels + + +// PrinterState current state of the printer. +type PrinterState struct { + Text string `json:"text"` + Flags struct { + Operations bool `json:"operational"` + Paused bool `json:"paused"` + Printing bool `json:"printing"` + SDReady bool `json:"sdReady"` + Error bool `json:"error"` + Ready bool `json:"ready"` + ClosedOnError bool `json:"closedOrError"` + } `json:"flags"` +} diff --git a/octoprintApis/dataModels/Profile.go b/octoprintApis/dataModels/Profile.go new file mode 100755 index 00000000..cdbef844 --- /dev/null +++ b/octoprintApis/dataModels/Profile.go @@ -0,0 +1,10 @@ +package dataModels + +// Profile describe a printer profile. +type Profile struct { + // ID is the identifier of the profile. + ID string `json:"id"` + + // Name is the display name of the profile. + Name string `json:"name"` +} diff --git a/octoprintApis/ProgressInformation.go b/octoprintApis/dataModels/ProgressInformation.go similarity index 97% rename from octoprintApis/ProgressInformation.go rename to octoprintApis/dataModels/ProgressInformation.go index 194b5fb2..1d5ad5f4 100755 --- a/octoprintApis/ProgressInformation.go +++ b/octoprintApis/dataModels/ProgressInformation.go @@ -1,4 +1,4 @@ -package octoprintApis +package dataModels import ( // "encoding/json" @@ -7,6 +7,7 @@ import ( // "time" ) + // Progress information // https://docs.octoprint.org/en/master/api/datamodel.html#progress-information diff --git a/octoprintApis/dataModels/Reference.go b/octoprintApis/dataModels/Reference.go new file mode 100755 index 00000000..d38c50ef --- /dev/null +++ b/octoprintApis/dataModels/Reference.go @@ -0,0 +1,16 @@ +package dataModels + + +// Reference of a file. +type Reference struct { + // Resource that represents the file or folder (e.g. for issuing commands + // to or for deleting) + Resource string `json:"resource"` + + // Download URL for the file. Never present for folders. + Download string `json:"download"` + + // Model from which this file was generated (e.g. an STL, currently not + // used). Never present for folders. + Model string `json:"model"` +} diff --git a/octoprintApis/dataModels/SdState.go b/octoprintApis/dataModels/SdState.go new file mode 100755 index 00000000..6121467f --- /dev/null +++ b/octoprintApis/dataModels/SdState.go @@ -0,0 +1,7 @@ +package dataModels + + +// SdState is the state of the sd reader. +type SdState struct { + IsReady bool `json:"ready"` +} diff --git a/octoprintApis/dataModels/SerialConfig.go b/octoprintApis/dataModels/SerialConfig.go new file mode 100755 index 00000000..b9dd6943 --- /dev/null +++ b/octoprintApis/dataModels/SerialConfig.go @@ -0,0 +1,102 @@ +package dataModels + + +// SerialConfig settings to configure the serial connection to the printer. +type SerialConfig struct { + // Port is the default serial port, defaults to unset (= AUTO) + Port string `json:"port"` + + // Baudrate is the default baudrate, defaults to unset (= AUTO) + Baudrate int `json:"baudrate"` + + // Available serial ports + PortOptions []string `json:"portOptions"` + + // Available serial baudrates + BaudrateOptions []int `json:"baudrateOptions"` + + // Autoconnect whether to automatically connect to the printer on server + // startup (if available). + Autoconnect bool `json:"autoconnect"` + + // TimeoutConnection for waiting to establish a connection with the selected + // port, in seconds. Defaults to 2 sec. Maps to serial.timeout.connection in + // config.yaml + TimeoutConnection float64 `json:"timeoutConnection"` + + // TimeoutDetection for waiting for a response from the currently tested + // port during autodetect, in seconds. Defaults to 0.5 sec Maps to + // serial.timeout.detection in config.yaml + TimeoutDetection float64 `json:"timeoutDetection"` + + // TimeoutCommunication during serial communication, in seconds. Defaults to + // 30 sec. Maps to serial.timeout.communication in config.yaml + TimeoutCommunication float64 `json:"timeoutCommunication"` + + // TimeoutTemperature after which to query temperature when no target is + // set. Maps to serial.timeout.temperature in config.yaml + TimeoutTemperature float64 `json:"timeoutTemperature"` + + // TimeoutTemperatureTargetSet after which to query temperature when a + // target is set. Maps to serial.timeout.temperatureTargetSet in config.yaml + TimeoutTemperatureTargetSet float64 `json:"timeoutTemperatureTargetSet"` + + // TimeoutSDStatus after which to query the SD status while SD printing. + // Maps to serial.timeout.sdStatus in config.yaml + TimeoutSdStatus float64 `json:"timeoutSdStatus"` + + // Log whether to log whole communication to serial.log (warning: might + // decrease performance) + Log bool `json:"log"` + + // AdditionalPorts use this to define additional patterns to consider for + // serial port listing. Must be a valid "glob" pattern (see + // http://docs.python.org/2/library/glob.html). Defaults to not set. + AdditionalPorts []string `json:"additionalPorts"` + + // AdditionalBaudrates use this to define additional baud rates to offer for + // connecting to serial ports. Must be a valid integer. Defaults to not set + AdditionalBaudrates []int `json:"additionalBaudrates"` + + // LongRunningCommands which are known to take a long time to be + // acknowledged by the firmware. E.g. homing, dwelling, auto leveling etc. + LongRunningCommands []string `json:"longRunningCommands"` + + // ChecksumRequiringCommands which need to always be send with a checksum. + // Defaults to only M110 + ChecksumRequiringCommands []string `json:"checksumRequiringCommands"` + + // HelloCommand to send in order to initiate a handshake with the printer. + // Defaults to "M110 N0" which simply resets the line numbers in the + // firmware and which should be acknowledged with a simple "ok". + HelloCommand string `json:"helloCommand"` + + // IgnoreErrorsFromFirmware whether to completely ignore errors from the + // firmware or not + IgnoreErrorsFromFirmware bool `json:"ignoreErrorsFromFirmware"` + + // DisconnectOnErrors whether to disconnect on errors or not. + DisconnectOnErrors bool `json:"disconnectOnErrors"` + + // TriggerOkForM29 whether to "manually" trigger an ok for M29 (a lot of + // versions of this command are buggy and the responds skips on the ok) + TriggerOkForM29 bool `json:"triggerOkForM29"` + + // SupportResendsWithoutOk whether to support resends without follow-up ok + // or not. + SupportResendsWithoutOk string `json:"supportResendsWithoutOk"` + + // Maps to serial.maxCommunicationTimeouts.idle in config.yaml + MaxTimeoutsIdle float64 `json:"maxTimeoutsIdle"` + + // MaxTimeoutsPrinting maximum number of consecutive communication timeouts + // after which the printer will be considered dead and OctoPrint disconnects + // with an error. Maps to serial.maxCommunicationTimeouts.printing in + // config.yaml + MaxTimeoutsPrinting float64 `json:"maxTimeoutsPrinting"` + + // MaxTimeoutsPrinting maximum number of consecutive communication timeouts + // after which the printer will be considered dead and OctoPrint disconnects + // with an error. Maps to serial.maxCommunicationTimeouts.log in config.yaml + MaxTimeoutsLong float64 `json:"maxTimeoutsLong"` +} diff --git a/octoprintApis/dataModels/ServerConfig.go b/octoprintApis/dataModels/ServerConfig.go new file mode 100755 index 00000000..58f09d78 --- /dev/null +++ b/octoprintApis/dataModels/ServerConfig.go @@ -0,0 +1,58 @@ +package dataModels + + +// ServerConfig settings to configure the server. +type ServerConfig struct { + // Commands to restart/shutdown octoprint or the system it's running on. + Commands struct { + // ServerRestartCommand to restart OctoPrint, defaults to being unset + ServerRestartCommand string `json:"serverRestartCommand"` + + //SystemRestartCommand to restart the system OctoPrint is running on, + // defaults to being unset + SystemRestartCommand string `json:"systemRestartCommand"` + + // SystemShutdownCommand Command to shut down the system OctoPrint is + // running on, defaults to being unset + SystemShutdownCommand string `json:"systemShutdownCommand"` + } `json:"commands"` + + // Diskspace settings of when to display what disk space warning + Diskspace struct { + // Warning threshold (bytes) after which to consider disk space becoming + // sparse, defaults to 500MB. + Warning uint64 `json:"warning"` + + // Critical threshold (bytes) after which to consider disk space becoming + // critical, defaults to 200MB. + Critical uint64 `json:"critical"` + } `json:"diskspace"` + + // OnlineCheck configuration of the regular online connectivity check. + OnlineCheck struct { + // Enabled whether the online check is enabled, defaults to false due to + // valid privacy concerns. + IsEnabled bool `json:"enabled"` + + // Interval in which to check for online connectivity (in seconds) + Interval int `json:"interval"` + + // Host DNS host against which to check (default: 8.8.8.8 aka Google's DNS) + Host string `json:"host"` + + // DNS port against which to check (default: 53 - the default DNS port) + Port int `json:"port"` + } `json:"onlineCheck"` + + // PluginBlacklist configuration of the plugin blacklist + PluginBlacklist struct { + // Enabled whether use of the blacklist is enabled, defaults to false + IsEnabled bool `json:"enabled"` + + // URL from which to fetch the blacklist + URL string `json:"url"` + + // TTL is time to live of the cached blacklist, in secs (default: 15mins) + TTL int `json:"ttl"` + } `json:"pluginBlacklist"` +} diff --git a/octoprintApis/dataModels/SettingsResponse.go b/octoprintApis/dataModels/SettingsResponse.go new file mode 100755 index 00000000..c6158737 --- /dev/null +++ b/octoprintApis/dataModels/SettingsResponse.go @@ -0,0 +1,35 @@ +package dataModels + + +// Settings are the current configuration of OctoPrint. +type SettingsResponse struct { + // API REST API settings. + API *APIConfig `json:"api"` + + // Features settings to enable or disable OctoPrint features. + Feature *FeaturesConfig `json:"feature"` + + //Folder settings to set custom paths for folders used by OctoPrint. + Folder *FolderConfig `json:"folder"` + + // Serial settings to configure the serial connection to the printer. + Serial *SerialConfig `json:"serial"` + + // Server settings to configure the server. + Server *ServerConfig `json:"server"` + + // Temperature profiles which will be displayed in the temperature tab. + Temperature *TemperatureConfig `json:"temperature"` + + // TerminalFilters to display in the terminal tab for filtering certain + // lines from the display terminal log. + TerminalFilters []*TerminalFilter `json:"terminalFilters"` + + // Webcam settings to configure webcam support. + Webcam *WebcamConfig `json:"json"` + + // Un-handled values + Appearance interface{} `json:"appearance"` + Plugins interface{} `json:"plugins"` + Printer interface{} `json:"printer"` +} diff --git a/octoprintApis/dataModels/SystemCommandsResponse.go b/octoprintApis/dataModels/SystemCommandsResponse.go new file mode 100755 index 00000000..80a31cd9 --- /dev/null +++ b/octoprintApis/dataModels/SystemCommandsResponse.go @@ -0,0 +1,8 @@ +package dataModels + + +// SystemCommandsResponse is the response to a SystemCommandsRequest. +type SystemCommandsResponse struct { + Core []*CommandDefinition `json:"core"` + Custom []*CommandDefinition `json:"custom"` +} diff --git a/octoprintApis/dataModels/TemperatureConfig.go b/octoprintApis/dataModels/TemperatureConfig.go new file mode 100755 index 00000000..03794f04 --- /dev/null +++ b/octoprintApis/dataModels/TemperatureConfig.go @@ -0,0 +1,21 @@ +package dataModels + + +// TemperatureConfig temperature profiles which will be displayed in the +// temperature tab. +type TemperatureConfig struct { + // Graph cutoff in minutes. + Cutoff int `json:"cutoff"` + + // Profiles which will be displayed in the temperature tab. + TemperaturePresets []*TemperaturePreset `json:"profiles"` + + // SendAutomatically enable this to have temperature fine adjustments you + // do via the + or - button be sent to the printer automatically. + SendAutomatically bool `json:"sendAutomatically"` + + // SendAutomaticallyAfter OctoPrint will use this delay to limit the number + // of sent temperature commands should you perform multiple fine adjustments + // in a short time. + SendAutomaticallyAfter float64 `json:"sendAutomaticallyAfter"` +} diff --git a/octoprintApis/TemperatureData.go b/octoprintApis/dataModels/TemperatureData.go similarity index 95% rename from octoprintApis/TemperatureData.go rename to octoprintApis/dataModels/TemperatureData.go index 1bc948e5..aefba0ee 100755 --- a/octoprintApis/TemperatureData.go +++ b/octoprintApis/dataModels/TemperatureData.go @@ -1,4 +1,4 @@ -package octoprintApis +package dataModels import ( // "encoding/json" @@ -7,6 +7,7 @@ import ( // "time" ) + // TemperatureData is temperature stats for a tool. type TemperatureData struct { // Actual current temperature. diff --git a/octoprintApis/dataModels/TemperatureDataResponse.go b/octoprintApis/dataModels/TemperatureDataResponse.go new file mode 100755 index 00000000..a5febc71 --- /dev/null +++ b/octoprintApis/dataModels/TemperatureDataResponse.go @@ -0,0 +1,13 @@ +package dataModels + +// FullStateResponse contains informantion about the current state of the printer. +type TemperatureDataResponse struct { + // TemperatureStateResponse is the printer’s temperature state data. + TemperatureStateResponse TemperatureStateResponse `json:"temperature"` + + // SD is the printer’s sd state data. + // SD SDState `json:"sd"` + + // State is the printer’s general state. + // State PrinterState `json:"state"` +} diff --git a/octoprintApis/dataModels/TemperaturePreset.go b/octoprintApis/dataModels/TemperaturePreset.go new file mode 100755 index 00000000..62e90f12 --- /dev/null +++ b/octoprintApis/dataModels/TemperaturePreset.go @@ -0,0 +1,9 @@ +package dataModels + + +// TemperaturePreset describes the temperature preset for a given material. +type TemperaturePreset struct { + Name string `json:"name"` + Bed float64 `json:"bed"` + Extruder float64 `json:"extruder"` +} diff --git a/octoprintApis/TemperatureStateResponse.go b/octoprintApis/dataModels/TemperatureStateResponse.go similarity index 97% rename from octoprintApis/TemperatureStateResponse.go rename to octoprintApis/dataModels/TemperatureStateResponse.go index 40754aa1..5021e534 100755 --- a/octoprintApis/TemperatureStateResponse.go +++ b/octoprintApis/dataModels/TemperatureStateResponse.go @@ -1,4 +1,4 @@ -package octoprintApis +package dataModels import ( "encoding/json" @@ -7,11 +7,9 @@ import ( // "time" ) - // TODO: add request // TODO: add Do() - // TemperatureState is the printer’s temperature state data. type TemperatureStateResponse temperatureStateResponse diff --git a/octoprintApis/dataModels/TerminalFilter.go b/octoprintApis/dataModels/TerminalFilter.go new file mode 100755 index 00000000..c5418057 --- /dev/null +++ b/octoprintApis/dataModels/TerminalFilter.go @@ -0,0 +1,9 @@ +package dataModels + + +// TerminalFilter to display in the terminal tab for filtering certain lines +// from the display terminal log. +type TerminalFilter struct { + Name string `json:"name"` + RegEx string `json:"regex"` +} diff --git a/octoprintApis/dataModels/UploadFileResponse.go b/octoprintApis/dataModels/UploadFileResponse.go new file mode 100755 index 00000000..6fdf8a52 --- /dev/null +++ b/octoprintApis/dataModels/UploadFileResponse.go @@ -0,0 +1,25 @@ +package dataModels + + +// UploadFileResponse is the response to a UploadFileRequest. +type UploadFileResponse struct { + // Abridged information regarding the file that was just uploaded. If only + // uploaded to local this will only contain the local property. If uploaded + // to SD card, this will contain both local and sdcard properties. Only + // contained if a file was uploaded, not present if only a new folder was + // created. + File struct { + // Local is the information regarding the file that was just uploaded + // to the local storage. + Local *FileResponse `json:"local"` + + // SDCard is the information regarding the file that was just uploaded + // to the printer’s SD card. + SDCard *FileResponse `json:"sdcard"` + } `json:"files"` + + // Done whether any file processing after upload has already finished or + // not, e.g. due to first needing to perform a slicing step. Clients may + // use this information to direct progress displays related to the upload. + IsDone bool `json:"done"` +} diff --git a/octoprintApis/dataModels/VersionResponse.go b/octoprintApis/dataModels/VersionResponse.go new file mode 100755 index 00000000..849f11d4 --- /dev/null +++ b/octoprintApis/dataModels/VersionResponse.go @@ -0,0 +1,12 @@ +package dataModels + + + +// VersionResponse is the response from a job command. +type VersionResponse struct { + // API is the API version. + API string `json:"api"` + + // Server is the server version. + Server string `json:"server"` +} diff --git a/octoprintApis/dataModels/WebcamConfig.go b/octoprintApis/dataModels/WebcamConfig.go new file mode 100755 index 00000000..4af195a0 --- /dev/null +++ b/octoprintApis/dataModels/WebcamConfig.go @@ -0,0 +1,41 @@ +package dataModels + + +// WebcamConfig settings to configure webcam support. +type WebcamConfig struct { + // StreamUrl use this option to enable display of a webcam stream in the + // UI, e.g. via MJPG-Streamer. Webcam support will be disabled if not + // set. Maps to webcam.stream in config.yaml. + StreamURL string `json:"streamUrl"` + + // SnapshotURL use this option to enable timelapse support via snapshot, + // e.g. via MJPG-Streamer. Timelapse support will be disabled if not set. + // Maps to webcam.snapshot in config.yaml. + SnapshotURL string `json:"snapshotUrl"` + + // FFmpegPath path to ffmpeg binary to use for creating timelapse + // recordings. Timelapse support will be disabled if not set. Maps to + // webcam.ffmpeg in config.yaml. + FFmpegPath string `json:"ffmpegPath"` + + // Bitrate to use for rendering the timelapse video. This gets directly + // passed to ffmpeg. + Bitrate int `json:"bitrate"` + + // FFmpegThreads number of how many threads to instruct ffmpeg to use for + // encoding. Defaults to 1. Should be left at 1 for RPi1. + FFmpegThreads int `json:"ffmpegThreads"` + + // Watermark whether to include a "created with OctoPrint" watermark in the + // generated timelapse movies. + Watermark string `json:"watermark"` + + // FlipH whether to flip the webcam horizontally. + FlipH bool `json:"flipH"` + + // FlipV whether to flip the webcam vertically. + FlipV bool `json:"flipV"` + + // Rotate90 whether to rotate the webcam 90° counter clockwise. + Rotate90 bool `json:"rotate90"` +} \ No newline at end of file diff --git a/octoprintApis/dataModels/ZOffsetResponse.go b/octoprintApis/dataModels/ZOffsetResponse.go new file mode 100755 index 00000000..8ead6039 --- /dev/null +++ b/octoprintApis/dataModels/ZOffsetResponse.go @@ -0,0 +1,7 @@ +package dataModels + + +type ZOffsetResponse struct { + // Job contains information regarding the target of the current print job. + Offset float64 `json:"offset"` +} diff --git a/octoprintApis/files.go b/octoprintApis/files.go index 2f461fb0..bfaa46ba 100755 --- a/octoprintApis/files.go +++ b/octoprintApis/files.go @@ -1,250 +1,41 @@ package octoprintApis import ( - "bytes" - "encoding/json" - "fmt" - "io" - "mime/multipart" + // "bytes" + // "encoding/json" + // "fmt" + // "io" + // "mime/multipart" + + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) -type Location string -const ( - // URIFiles = "/api/files" +const FilesApiUri = "/api/files" - Local Location = "local" - SDCard Location = "sdcard" -) var ( - FilesLocationGETErrors = StatusMapping{ + FilesLocationGETErrors = StatusMapping { 404: "Location is neither local nor sdcard", } - FilesLocationPOSTErrors = StatusMapping{ + + FilesLocationPOSTErrors = StatusMapping { 400: "No file or foldername are included in the request, userdata was provided but could not be parsed as JSON or the request is otherwise invalid.", 404: "Location is neither local nor sdcard or trying to upload to SD card and SD card support is disabled", 409: "The upload of the file would override the file that is currently being printed or if an upload to SD card was requested and the printer is either not operational or currently busy with a print job.", 415: "The file is neither a gcode nor an stl file (or it is an stl file but slicing support is disabled)", 500: "The upload failed internally", } - FilesLocationPathPOSTErrors = StatusMapping{ + + FilesLocationPathPOSTErrors = StatusMapping { 400: "The command is unknown or the request is otherwise invalid", 415: "A slice command was issued against something other than an STL file.", 404: "Location is neither local nor sdcard or the requested file was not found", 409: "Selected file is supposed to start printing directly but the printer is not operational or if a file to be sliced is supposed to be selected or start printing directly but the printer is not operational or already printing.", } - FilesLocationDeleteErrors = StatusMapping{ + + FilesLocationDeleteErrors = StatusMapping { 404: "Location is neither local nor sdcard", 409: "The file to be deleted is currently being printed", } ) - -// FileRequest is now in FileRequest.go -// TODO: remove this commented code -// FileRequest retrieves the selected file’s or folder’s information. -// type FileRequest struct { -// // Location of the file for which to retrieve the information, either -// // `local` or `sdcard`. -// Location Location - -// // Filename of the file for which to retrieve the information -// Filename string - -// // Recursive if set to true, return all files and folders recursively. -// // Otherwise only return items on same level. -// Recursive bool -// } - -// // Do sends an API request and returns the API response -// func (cmd *FileRequest) Do(c *Client) (*FileInformation, error) { -// uri := fmt.Sprintf("%s/%s/%s?recursive=%t", URIFiles, -// cmd.Location, cmd.Filename, cmd.Recursive, -// ) - -// b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) -// if err != nil { -// return nil, err -// } - -// r := &FileInformation{} -// if err := json.Unmarshal(b, r); err != nil { -// return nil, err -// } - -// return r, err -// } - - - - - -// FilesRequest retrieve information regarding all files currently available and -// regarding the disk space still available locally in the system. -type FilesRequest struct { - // Location is the target location . - Location Location - // Recursive if set to true, return all files and folders recursively. - // Otherwise only return items on same level. - Recursive bool -} - -// Do sends an API request and returns the API response. -func (cmd *FilesRequest) Do(c *Client) (*FilesResponse, error) { - uri := fmt.Sprintf("%s?recursive=%t", URIFiles, cmd.Recursive) - if cmd.Location != "" { - uri = fmt.Sprintf("%s/%s?recursive=%t", URIFiles, cmd.Location, cmd.Recursive) - } - - b, err := c.doJSONRequest("GET", uri, nil, FilesLocationGETErrors) - if err != nil { - return nil, err - } - - r := &FilesResponse{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - - if len(r.Children) > 0 { - r.Files = r.Children - } - - return r, err -} - -// UploadFileRequest uploads a file to the selected location or create a new -// empty folder on it. -type UploadFileRequest struct { - // Location is the target location to which to upload the file. Currently - // only `local` and `sdcard` are supported here, with local referring to - // OctoPrint’s `uploads` folder and `sdcard` referring to the printer’s - // SD card. If an upload targets the SD card, it will also be stored - // locally first. - Location Location - // Select whether to select the file directly after upload (true) or not - // (false). Optional, defaults to false. Ignored when creating a folder. - Select bool - //Print whether to start printing the file directly after upload (true) or - // not (false). If set, select is implicitely true as well. Optional, - // defaults to false. Ignored when creating a folder. - Print bool - b *bytes.Buffer - w *multipart.Writer -} - -// AddFile adds a new file to be uploaded from a given reader. -func (req *UploadFileRequest) AddFile(filename string, r io.Reader) error { - w, err := req.writer().CreateFormFile("file", filename) - if err != nil { - return err - } - - _, err = io.Copy(w, r) - return err - -} - -func (req *UploadFileRequest) writer() *multipart.Writer { - if req.w == nil { - req.b = bytes.NewBuffer(nil) - req.w = multipart.NewWriter(req.b) - } - - return req.w -} - -// AddFolder adds a new folder to be created. -func (req *UploadFileRequest) AddFolder(folder string) error { - return req.writer().WriteField("foldername", folder) -} - -// Do sends an API request and returns the API response. -func (req *UploadFileRequest) Do(c *Client) (*UploadFileResponse, error) { - req.addSelectPrintAndClose() - - uri := fmt.Sprintf("%s/%s", URIFiles, req.Location) - b, err := c.doRequest("POST", uri, req.w.FormDataContentType(), req.b, FilesLocationPOSTErrors) - if err != nil { - return nil, err - } - - r := &UploadFileResponse{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - - return r, err -} - -func (req *UploadFileRequest) addSelectPrintAndClose() error { - err := req.writer().WriteField("select", fmt.Sprintf("%t", req.Select)) - if err != nil { - return err - } - - err = req.writer().WriteField("print", fmt.Sprintf("%t", req.Print)) - if err != nil { - return err - } - - return req.writer().Close() -} - -// DeleteFileRequest delete the selected path on the selected location. -type DeleteFileRequest struct { - // Location is the target location on which to delete the file, either - // `local` (for OctoPrint’s uploads folder) or \sdcard\ for the printer’s - // SD card (if available) - Location Location - // Path of the file to delete - Path string -} - -// Do sends an API request and returns error if any. -func (req *DeleteFileRequest) Do(c *Client) error { - uri := fmt.Sprintf("%s/%s/%s", URIFiles, req.Location, req.Path) - if _, err := c.doJSONRequest("DELETE", uri, nil, FilesLocationDeleteErrors); err != nil { - return err - } - - return nil -} - -// SelectFileRequest is now in SelectFileRequest.go -// // SelectFileRequest selects a file for printing. -// type SelectFileRequest struct { -// // Location is target location on which to send the command for is located, -// // either local (for OctoPrint’s uploads folder) or sdcard for the -// // printer’s SD card (if available) -// Location Location `json:"-"` -// // Path of the file for which to issue the command -// Path string `json:"-"` -// // Print, if set to true the file will start printing directly after -// // selection. If the printer is not operational when this parameter is -// // present and set to true, the request will fail with a response of -// // 409 Conflict. -// Print bool `json:"print"` -// } - -// // Do sends an API request and returns an error if any. -// func (cmd *SelectFileRequest) Do(c *Client) error { -// b := bytes.NewBuffer(nil) -// if err := cmd.encode(b); err != nil { -// return err -// } - -// uri := fmt.Sprintf("%s/%s/%s", URIFiles, cmd.Location, cmd.Path) -// _, err := c.doJSONRequest("POST", uri, b, FilesLocationPathPOSTErrors) -// return err -// } - -// func (cmd *SelectFileRequest) encode(w io.Writer) error { -// return json.NewEncoder(w).Encode(struct { -// Command string `json:"command"` -// SelectFileRequest -// }{ -// Command: "select", -// SelectFileRequest: *cmd, -// }) -// } diff --git a/octoprintApis/files_test.go b/octoprintApis/files_test.go old mode 100644 new mode 100755 index 72b37ad8..48ddd38c --- a/octoprintApis/files_test.go +++ b/octoprintApis/files_test.go @@ -1,5 +1,6 @@ package octoprintApis +/* import ( "bytes" "testing" @@ -84,3 +85,4 @@ func xxxTestFilesRequest_DoWithLocation(t *testing.T) { assert.Len(t, files.Files, 0) } +*/ \ No newline at end of file diff --git a/octoprintApis/job.go b/octoprintApis/job.go index 6c6b69cc..9dd70398 100755 --- a/octoprintApis/job.go +++ b/octoprintApis/job.go @@ -1,175 +1,17 @@ package octoprintApis import ( - "bytes" - "encoding/json" - "io" - "log" + // "bytes" + // "encoding/json" + // "io" + // "log" ) -var JobToolErrors = StatusMapping{ - 409: "Printer is not operational or the current print job state does not match the preconditions for the command.", -} - - - - -// JobRequest is now in JobRequest.go -// // JobRequest retrieve information about the current job (if there is one). -// type JobRequest struct{} - -// // Do sends an API request and returns the API response. -// func (cmd *JobRequest) Do(c *Client) (*JobResponse, error) { -// bytes, err := c.doJSONRequest("GET", JobTool, nil, nil) -// if err != nil { -// return nil, err -// } - -// response := &JobResponse{} -// if err := json.Unmarshal(bytes, response); err != nil { -// return nil, err -// } - -// return response, err -// } - - - - - -// StartRequest starts the print of the currently selected file. -type StartRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *StartRequest) Do(c *Client) error { - payload := map[string]string{"command": "start"} - - buffer := bytes.NewBuffer(nil) - if err := json.NewEncoder(buffer).Encode(payload); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) - return err -} - -// CancelRequest cancels the current print job. -type CancelRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *CancelRequest) Do(c *Client) error { - payload := map[string]string{"command": "cancel"} - - buffer := bytes.NewBuffer(nil) - if err := json.NewEncoder(buffer).Encode(payload); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) - return err -} - -// RestartRequest restart the print of the currently selected file from the -// beginning. There must be an active print job for this to work and the print -// job must currently be paused -type RestartRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *RestartRequest) Do(c *Client) error { - payload := map[string]string{"command": "restart"} - - buffer := bytes.NewBuffer(nil) - if err := json.NewEncoder(buffer).Encode(payload); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) - return err -} +// https://docs.octoprint.org/en/master/api/job.html +const JobApiUri = "/api/job" -type PauseAction string -const ( - // Pause the current job if it’s printing, does nothing if it’s already paused. - Pause PauseAction = "pause" - - // Resume the current job if it’s paused, does nothing if it’s printing. - Resume PauseAction = "resume" - - // Toggle the pause state of the job, pausing it if it’s printing and - // resuming it if it’s currently paused. - Toggle PauseAction = "toggle" -) - -// PauseRequest pauses/resumes/toggles the current print job. -type PauseRequest struct { - // Action specifies which action to take. - // In order to stay backwards compatible to earlier iterations of this API, - // the default action to take if no action parameter is supplied is to - // toggle the print job status. - Action PauseAction `json:"action"` -} - -// Do sends an API request and returns an error if any. -func (cmd *PauseRequest) Do(c *Client) error { - buffer := bytes.NewBuffer(nil) - if err := cmd.encode(buffer); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", JobTool, buffer, JobToolErrors) - return err -} - - - - - - -// Do sends an API request and returns an error if any. -func (cmd *PauseRequest) DoWithLogging(c *Client) error { - log.Println("job.Do() - starting call") - - buffer := bytes.NewBuffer(nil) - err := cmd.encode(buffer) - if err != nil { - log.Println("job.Do() - encode() failed") - return err - } - - // str := string([]byte(buffer.Bytes)) - str := string(buffer.Bytes()) - log.Printf("job.Do() - bytes are: '%s' abc", str) - - - log.Println("job.Do() - about to call POST") - body, err2 := c.doJSONRequestWithLogging("POST", JobTool, buffer, JobToolErrors) - - log.Println("job.Do() - finished calling POST") - if err2 != nil { - log.Println("job.Do() - call to doJSONRequest() failed") - log.Printf("job.Do() - err2 is: %s", err2.Error()) - } - - if err2 == nil { - log.Println("job.Do() - call to doJSONRequest() passed") - str = string(body) - log.Printf("job.Do() - body is: %s", str) - } - - return err -} - - - - -func (cmd *PauseRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - PauseRequest - }{ - Command: "pause", - PauseRequest: *cmd, - }) +var JobToolErrors = StatusMapping { + 409: "Printer is not operational or the current print job state does not match the preconditions for the command.", } diff --git a/octoprintApis/plugin_manager.go b/octoprintApis/plugin_manager.go deleted file mode 100755 index 375ad8c5..00000000 --- a/octoprintApis/plugin_manager.go +++ /dev/null @@ -1,76 +0,0 @@ -package octoprintApis - -import ( - "bytes" - "encoding/json" - "log" -) - -const pluginManagerRequestURI = "/api/plugin/pluginmanager" - - -// Plugin - -type Plugin struct { - Author string `json:"author"` - Blacklisted bool `json:"blacklisted"` - Bundled bool `json:"bundled"` - Description string `json:"description"` - // DisablingDiscouraged bool `json:"disabling_discouraged"` - Enabled bool `json:"enabled"` - ForcedDisabled bool `json:"forced_disabled"` - Incompatible bool `json:"incompatible"` - Key string `json:"key"` - License string `json:"license"` - Managable bool `json:"managable"` - Name string `json:"name"` - // notifications: [] - Origin string `json:"origin"` - PendingDisable bool `json:"pending_disable"` - PendingEnable bool `json:"pending_enable"` - PendingInstall bool `json:"pending_install"` - PendingUninstall bool `json:"pending_uninstall"` - Python string `json:"python"` - SafeModeVictim bool `json:"safe_mode_victim"` - URL string `json:"url"` - Version string `json:"version"` -} - -// GetPluginManagerInfoRequest - -type GetPluginManagerInfoRequest struct { - Command string `json:"command"` -} - -// GetPluginManagerInfoResponse - -type GetPluginManagerInfoResponse struct { - Octoprint string `json:"octoprint"` - Online bool `json:"online"` - //orphan_data: { } - OS string `json:"os"` - //pip: {} - Plugins []Plugin `json:"plugins"` -} - -// Do - -func (cmd *GetPluginManagerInfoRequest) Do(c *Client) (*GetPluginManagerInfoResponse, error) { - cmd.Command = "get_settings" - - params := bytes.NewBuffer(nil) - if err := json.NewEncoder(params).Encode(cmd); err != nil { - log.Println("plugin_manager.Do() - Encode() failed") - return nil, err - } - - b, err := c.doJSONRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) - if err != nil { - log.Println("plugin_manager.Do() - doJSONRequest() failed") - return nil, err - } - - r := &GetPluginManagerInfoResponse{} - if err := json.Unmarshal(b, r); err != nil { - log.Println("plugin_manager.Do() - Unmarshal() failed") - return nil, err - } - - return r, err -} diff --git a/octoprintApis/printer.go b/octoprintApis/printer.go index 77657313..3d58a8b9 100755 --- a/octoprintApis/printer.go +++ b/octoprintApis/printer.go @@ -3,668 +3,63 @@ package octoprintApis import ( "bytes" "encoding/json" - "fmt" - "io" - "log" + // "fmt" + // "io" + // "log" // "strings" -) -const ( - // URIPrinter = "/api/printer" - URIPrintHead = "/api/printer/printhead" - URIPrintTool = "/api/printer/tool" - URIPrintBed = "/api/printer/bed" - URIPrintSD = "/api/printer/sd" - URICommand = "/api/printer/command" - URICommandCustom = "/api/printer/command/custom" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) + +const PrinterPrintHeadApiUri = "/api/printer/printhead" +const PrinterToolApiUri = "/api/printer/tool" +const PrinterBedApiUri = "/api/printer/bed" +const PrinterSdApiUri = "/api/printer/sd" +const PrinterCommandApiUri = "/api/printer/command" +const PrinterCommandCustomApiUri = "/api/printer/command/custom" + + var ( - PrintErrors = StatusMapping{ + PrintErrors = StatusMapping { 409: "Printer is not operational", } - PrintHeadJobErrors = StatusMapping{ + + PrintHeadJobErrors = StatusMapping { 400: "Invalid axis specified, invalid value for travel amount for a jog command or factor for feed rate or otherwise invalid request", 409: "Printer is not operational or currently printing", } - PrintToolErrors = StatusMapping{ + + PrintToolErrors = StatusMapping { 400: "Targets or offsets contains a property or tool contains a value not matching the format tool{n}, the target/offset temperature, extrusion amount or flow rate factor is not a valid number or outside of the supported range, or if the request is otherwise invalid", 409: "Printer is not operational", } - PrintBedErrors = StatusMapping{ + + PrintBedErrors = StatusMapping { 409: "Printer is not operational or the selected printer profile does not have a heated bed.", } - PrintSDErrors = StatusMapping{ + + PrintSdErrors = StatusMapping { 404: "SD support has been disabled in OctoPrint’s settings.", 409: "SD card has not been initialized.", } ) - - - - -// FullStateRequest has been moved to FullStateRequest.go -// // FullStateRequest retrieves the current state of the printer. -// type FullStateRequest struct { -// // bytes if true retrieve the temperature history. -// IncludeHistory bool - -// // Limit limits the amount of returned history data points. -// Limit int - -// // Exclude list of fields to exclude from the response (e.g. if not -// // needed by the client). Valid values to supply here are `temperature`, -// // `sd` and `state`. -// Exclude []string -// } - -// // FullStateResponse contains informantion about the current state of the printer. -// type FullStateResponse struct { -// // TemperatureStateResponse is the printer’s temperature state data. -// Temperature TemperatureStateResponse `json:"temperature"` - -// // SD is the printer’s sd state data. -// SD SDState `json:"sd"` - -// // State is the printer’s general state. -// State PrinterState `json:"state"` -// } - -// // Do sends an API request and returns the API response. -// func (cmd *FullStateRequest) Do(c *Client) (*FullStateResponse, error) { -// uri := fmt.Sprintf( -// "%s?history=%t&limit=%d&exclude=%s", -// URIPrinter, -// cmd.IncludeHistory, -// cmd.Limit, -// strings.Join(cmd.Exclude, ","), -// ) - -// log.Printf("TODO-Remove: StateRequest (FullStateResponse) uri is: %s", uri) -// //StateRequest uri is: %s /api/printer?history=true&limit=1&exclude=sd,state -// /* -// { -// "temperature": { -// "bed": { -// "actual": 26.9, -// "offset": 0, -// "target": 0.0 -// }, -// "history": [ -// { -// "bed": { -// "actual": 26.9, -// "target": 0.0 -// }, -// "time": 1598235178, -// "tool0": { -// "actual": 35.4, -// "target": 0.0 -// } -// } -// ], -// "tool0": { -// "actual": 35.4, -// "offset": 0, -// "target": 0.0 -// } -// } -// } -// */ - - -// bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) -// if err != nil { -// return nil, err -// } - -// response := &FullStateResponse{} -// if err := json.Unmarshal(bytes, response); err != nil { -// return nil, err -// } - -// return response, err -// } - - - - - - -// FullStateRequest retrieves the current state of the printer. -type TemperatureDataRequest struct { - // bytes if true retrieve the temperature history. - // IncludeHistory bool - - // Limit limits the amount of returned history data points. - // Limit int - - // Exclude list of fields to exclude from the response (e.g. if not - // needed by the client). Valid values to supply here are `temperature`, - // `sd` and `state`. - // Exclude []string -} - -// FullStateResponse contains informantion about the current state of the printer. -type TemperatureDataResponse struct { - // TemperatureStateResponse is the printer’s temperature state data. - TemperatureStateResponse TemperatureStateResponse `json:"temperature"` - - // SD is the printer’s sd state data. - // SD SDState `json:"sd"` - - // State is the printer’s general state. - // State PrinterState `json:"state"` -} - -// Do sends an API request and returns the API response. -func (cmd *TemperatureDataRequest) Do(c *Client) (*TemperatureDataResponse, error) { - uri := fmt.Sprintf( - "%s?history=false&exclude=sd,state", - URIPrinter, - ) - - log.Printf("TODO-Remove: StateRequest (TemperatureDataResponse) uri is: %s", uri) - //StateRequest uri is: %s /api/printer?history=false&exclude=sd,state - /* - { - "temperature": { - "bed": { - "actual": 26.9, - "offset": 0, - "target": 0.0 - }, - "tool0": { - "actual": 35.4, - "offset": 0, - "target": 0.0 - } - } - } - */ - - - bytes, err := c.doJSONRequest("GET", uri, nil, PrintErrors) - if err != nil { - return nil, err - } - - response := &TemperatureDataResponse{} - if err := json.Unmarshal(bytes, response); err != nil { - return nil, err - } - - return response, err -} - - - - - - - - - - - - - - - - - - - -// PrintHeadJogRequest jogs the print head (relatively) by a defined amount in -// one or more axes. -type PrintHeadJogRequest struct { - // X is the amount distance to travel in mm or coordinate to jog print head - // on x axis. - X float64 `json:"x,omitempty"` - // Y is the amount distance to travel in mm or coordinate to jog print head - // on y axis. - Y float64 `json:"y,omitempty"` - // Z is the amount distance to travel in mm.or coordinate to jog print head - // on x axis. - Z float64 `json:"z,omitempty"` - // Absolute is whether to move relative to current position (provided axes - // values are relative amounts) or to absolute position (provided axes - // values are coordinates) - Absolute bool `json:"absolute"` - // Speed at which to move in mm/s. If not provided, minimum speed for all - // selected axes from printer profile will be used. - Speed int `json:"speed,omitempty"` -} - -// Do sends an API request and returns an error if any. -func (cmd *PrintHeadJogRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintHead, b, PrintHeadJobErrors) - - return err -} - -func (cmd *PrintHeadJogRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - PrintHeadJogRequest - }{ - Command: "jog", - PrintHeadJogRequest: *cmd, - }) -} - -// PrintHeadHomeRequest homes the print head in all of the given axes. -type PrintHeadHomeRequest struct { - // Axes is a list of axes which to home. - Axes []Axis `json:"axes"` -} - -// Do sends an API request and returns an error if any. -func (cmd *PrintHeadHomeRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintHead, b, PrintHeadJobErrors) - return err -} - -func (cmd *PrintHeadHomeRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - PrintHeadHomeRequest - }{ - Command: "home", - PrintHeadHomeRequest: *cmd, - }) -} - -// ToolStateRequest retrieves the current temperature data (actual, target and -// offset) plus optionally a (limited) history (actual, target, timestamp) for -// all of the printer’s available tools. -type ToolStateRequest struct { - // History if true retrieve the temperature history. - IncludeHistory bool - - // Limit limtis amount of returned history data points. - Limit int -} - -// Do sends an API request and returns the API response. -func (cmd *ToolStateRequest) Do(c *Client) (*TemperatureStateResponse, error) { - uri := fmt.Sprintf("%s?history=%t&limit=%d", URIPrintTool, cmd.IncludeHistory, cmd.Limit) - - log.Printf("TODO-Remove: ToolStateRequest uri is: %s", uri) - //ToolStateRequest uri is: %s /api/printer/tool?history=true&limit=1 - /* - { - "history": [ - { - "tool0": { - "actual": 38.0, - "target": 0.0 - } - } - ], - "tool0": { - "actual": 38.0, - "offset": 0, - "target": 0.0 - } - } - */ - - b, err := c.doJSONRequest("GET", uri, nil, nil) - if err != nil { - return nil, err - } - - r := &TemperatureStateResponse{} - if err := json.Unmarshal(b, &r); err != nil { - return nil, err - } - - return r, err -} - -// ToolTargetRequest sets the given target temperature on the printer’s tools. -type ToolTargetRequest struct { - // Target temperature(s) to set, key must match the format tool{n} with n - // being the tool’s index starting with 0. - Targets map[string]float64 `json:"targets"` -} - -// Do sends an API request and returns an error if any. -func (cmd *ToolTargetRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *ToolTargetRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ToolTargetRequest - }{ - Command: "target", - ToolTargetRequest: *cmd, - }) -} - -// ToolOffsetRequest sets the given temperature offset on the printer’s tools. -type ToolOffsetRequest struct { - // Offset is offset(s) to set, key must match the format tool{n} with n - // being the tool’s index starting with 0. - Offsets map[string]float64 `json:"offsets"` -} - -// Do sends an API request and returns an error if any. -func (cmd *ToolOffsetRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *ToolOffsetRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ToolOffsetRequest - }{ - Command: "offset", - ToolOffsetRequest: *cmd, - }) -} - -// ToolExtrudeRequest extrudes the given amount of filament from the currently -// selected tool. -type ToolExtrudeRequest struct { - // Amount is the amount of filament to extrude in mm. May be negative to - // retract. - Amount int `json:"amount"` -} - -// Do sends an API request and returns an error if any. -func (cmd *ToolExtrudeRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *ToolExtrudeRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ToolExtrudeRequest - }{ - Command: "extrude", - ToolExtrudeRequest: *cmd, - }) -} - -// ToolSelectRequest selects the printer’s current tool. -type ToolSelectRequest struct { - // Tool to select, format tool{n} with n being the tool’s index starting - // with 0. - Tool string `json:"tool"` -} - -// Do sends an API request and returns an error if any. -func (cmd *ToolSelectRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *ToolSelectRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ToolSelectRequest - }{ - Command: "select", - ToolSelectRequest: *cmd, - }) -} - - - - - - -// ToolFlowRateRequest changes the flow rate factor to apply to extrusion of the tool. -type ToolFlowRateRequest struct { - // Factor is the new factor, percentage as integer, between 75 and 125%. - Factor int `json:"factor"` -} - -// Do sends an API request and returns an error if any. -func (cmd *ToolFlowRateRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *ToolFlowRateRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - ToolFlowRateRequest - }{ - Command: "flowrate", - ToolFlowRateRequest: *cmd, - }) -} - - - - - - - - -// BedStateRequest retrieves the current temperature data (actual, target and -// offset) plus optionally a (limited) history (actual, target, timestamp) for -// the printer’s heated bed. -// -// It’s also possible to retrieve the temperature history by supplying the -// history query parameter set to true. The amount of returned history data -// points can be limited using the limit query parameter. -type BedStateRequest struct { - // History if true retrieve the temperature history. - IncludeHistory bool - - // Limit limtis amount of returned history data points. - Limit int -} - -// Do sends an API request and returns the API response. -func (cmd *BedStateRequest) Do(c *Client) (*TemperatureStateResponse, error) { - uri := fmt.Sprintf("%s?history=%t&limit=%d", URIPrintBed, cmd.IncludeHistory, cmd.Limit) - b, err := c.doJSONRequest("GET", uri, nil, PrintBedErrors) - if err != nil { - return nil, err - } - - r := &TemperatureStateResponse{} - if err := json.Unmarshal(b, &r); err != nil { - return nil, err - } - - return r, err -} - -// BedTargetRequest sets the given target temperature on the printer’s bed. -type BedTargetRequest struct { - // Target temperature to set. - Target float64 `json:"target"` -} - -// Do sends an API request and returns an error if any. -func (cmd *BedTargetRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintBed, b, PrintBedErrors) - return err -} - -func (cmd *BedTargetRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - BedTargetRequest - }{ - Command: "target", - BedTargetRequest: *cmd, - }) -} - -// BedOffsetRequest sets the given temperature offset on the printer’s bed. -type BedOffsetRequest struct { - // Offset is offset to set. - Offset int `json:"offset"` -} - -// Do sends an API request and returns an error if any. -func (cmd *BedOffsetRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URIPrintTool, b, PrintToolErrors) - return err -} - -func (cmd *BedOffsetRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { - Command string `json:"command"` - BedOffsetRequest - }{ - Command: "offset", - BedOffsetRequest: *cmd, - }) -} - -// CommandRequest sends any command to the printer via the serial interface. -// Should be used with some care as some commands can interfere with or even -// stop a running print job. -type CommandRequest struct { - // Commands list of commands to send to the printer. - Commands []string `json:"commands"` -} - -// Do sends an API request and returns an error if any. -func (cmd *CommandRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(cmd); err != nil { - return err - } - - _, err := c.doJSONRequest("POST", URICommand, b, nil) - return err -} - -// CustomCommandsRequest retrieves all configured system controls. -type CustomCommandsRequest struct{} - -// Do sends an API request and returns the API response. -func (cmd *CustomCommandsRequest) Do(c *Client) (*CustomCommandsResponse, error) { - b, err := c.doJSONRequest("GET", URICommandCustom, nil, nil) - if err != nil { - return nil, err - } - - r := &CustomCommandsResponse{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - - return r, err -} - -// SDStateRequest retrieves the current state of the printer’s SD card. For this -// request no authentication is needed. -type SDStateRequest struct{} - -// Do sends an API request and returns the API response. -func (cmd *SDStateRequest) Do(c *Client) (*SDState, error) { - b, err := c.doJSONRequest("GET", URIPrintSD, nil, PrintSDErrors) - if err != nil { - return nil, err - } - - r := &SDState{} - if err := json.Unmarshal(b, r); err != nil { - return nil, err - } - - return r, err -} - -// SDInitRequest initializes the printer’s SD card, making it available for use. -// This also includes an initial retrieval of the list of files currently stored -// on the SD card. -type SDInitRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *SDInitRequest) Do(c *Client) error { - return doCommandRequest(c, URIPrintSD, "init", PrintSDErrors) -} - -// SDRefreshRequest Refreshes the list of files stored on the printer’s SD card. -type SDRefreshRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *SDRefreshRequest) Do(c *Client) error { - return doCommandRequest(c, URIPrintSD, "refresh", PrintSDErrors) -} - -// SDReleaseRequest releases the SD card from the printer. The reverse operation -// to init. After issuing this command, the SD card won’t be available anymore, -// hence and operations targeting files stored on it will fail. -type SDReleaseRequest struct{} - -// Do sends an API request and returns an error if any. -func (cmd *SDReleaseRequest) Do(c *Client) error { - return doCommandRequest(c, URIPrintSD, "release", PrintSDErrors) -} - -// doCommandRequest can be used in any operation where the only required field -// is the `command` field. -func doCommandRequest(c *Client, uri, command string, m StatusMapping) error { +// doCommandRequest can be used in any operation where the only required field is the `command` field. +func doCommandRequest( + client *Client, + uri string, + command string, + statusMapping StatusMapping, +) error { v := map[string]string{"command": command} - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(v); err != nil { + buffer := bytes.NewBuffer(nil) + if err := json.NewEncoder(buffer).Encode(v); err != nil { return err } - _, err := c.doJSONRequest("POST", uri, b, m) + _, err := client.doJsonRequest("POST", uri, buffer, statusMapping) + return err } diff --git a/octoprintApis/printer_test.go b/octoprintApis/printer_test.go index 31913b9c..dd0bf8f5 100755 --- a/octoprintApis/printer_test.go +++ b/octoprintApis/printer_test.go @@ -1,16 +1,18 @@ package octoprintApis +/* import ( "testing" "time" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/stretchr/testify/assert" ) func TestStateRequest_Do(t *testing.T) { cli := NewClient("http://localhost:5000", "") - r := &StateRequest{} + r := &octoprintApis.StateRequest{} state, err := r.Do(cli) assert.NoError(t, err) @@ -22,7 +24,7 @@ func TestStateRequest_Do(t *testing.T) { func TestStateRequest_DoWithHistory(t *testing.T) { cli := NewClient("http://localhost:5000", "") - r := &StateRequest{ + r := &octoprintApis.StateRequest{ IncludeHistory: true, } state, err := r.Do(cli) @@ -36,7 +38,7 @@ func TestStateRequest_DoWithHistory(t *testing.T) { func TestStateRequest_DoWithExclude(t *testing.T) { cli := NewClient("http://localhost:5000", "") - r := &StateRequest{Exclude: []string{"temperature"}} + r := &octoprintApis.StateRequest{Exclude: []string{"temperature"}} state, err := r.Do(cli) assert.NoError(t, err) @@ -95,3 +97,4 @@ func TestCustomCommandsRequest_Do(t *testing.T) { assert.Equal(t, s.Controls[0].Children[0].Name, "Move X (static)") assert.Len(t, s.Controls[0].Children[0].Commands, 3) } +*/ \ No newline at end of file diff --git a/octoprintApis/settings.go b/octoprintApis/settings.go index f676e04e..c59b5840 100755 --- a/octoprintApis/settings.go +++ b/octoprintApis/settings.go @@ -1,20 +1,26 @@ package octoprintApis -import "encoding/json" +import ( + "encoding/json" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +const SettingsApiUri = "/api/settings" -const URISettings = "/api/settings" // SettingsRequest retrieves the current configuration of OctoPrint. type SettingsRequest struct{} // Do sends an API request and returns the API response. -func (cmd *SettingsRequest) Do(c *Client) (*SettingsResponse, error) { - bytes, err := c.doJSONRequest("GET", URISettings, nil, nil) +func (cmd *SettingsRequest) Do(c *Client) (*dataModels.SettingsResponse, error) { + bytes, err := c.doJsonRequest("GET", SettingsApiUri, nil, nil) if err != nil { return nil, err } - response := &SettingsResponse{} + response := &dataModels.SettingsResponse{} if err := json.Unmarshal(bytes, response); err != nil { return nil, err } diff --git a/octoprintApis/settings_test.go b/octoprintApis/settings_test.go old mode 100644 new mode 100755 index 32279325..2d67f2a0 --- a/octoprintApis/settings_test.go +++ b/octoprintApis/settings_test.go @@ -1,5 +1,6 @@ package octoprintApis +/* import ( "testing" @@ -15,3 +16,4 @@ func TestSettingsRequest_Do(t *testing.T) { assert.Equal(t, settings.API.Enabled, true) } +*/ \ No newline at end of file diff --git a/octoprintApis/system.go b/octoprintApis/system.go index f9e7844c..80063f73 100755 --- a/octoprintApis/system.go +++ b/octoprintApis/system.go @@ -3,26 +3,35 @@ package octoprintApis import ( "encoding/json" "fmt" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) -var ExecuteErrors = StatusMapping{ + +const SystemCommandsApiUri = "/api/system/commands" + + +var ExecuteErrors = StatusMapping { 404: "The command could not be found for source and action", 500: "The command didn’t define a command to execute, the command returned a non-zero return code and ignore was not true or some other internal server error occurred", } -const URISystemCommands = "/api/system/commands" // SystemCommandsRequest retrieves all configured system commands. type SystemCommandsRequest struct{} // Do sends an API request and returns the API response. -func (cmd *SystemCommandsRequest) Do(c *Client) (*SystemCommandsResponse, error) { - b, err := c.doJSONRequest("GET", URISystemCommands, nil, nil) +func (cmd *SystemCommandsRequest) Do(c *Client) (*dataModels.SystemCommandsResponse, error) { + b, err := c.doJsonRequest("GET", SystemCommandsApiUri, nil, nil) if err != nil { return nil, err } - r := &SystemCommandsResponse{} + // TODO: there are 2 warnings here... the 2nd parameter into Unmarshal() + // is supposed to be a point. Change x.Confirm to &x.Confirm ? + // need to verify + + r := &dataModels.SystemCommandsResponse{} if err := json.Unmarshal(b, r); err != nil { return nil, err } @@ -45,7 +54,7 @@ func (cmd *SystemCommandsRequest) Do(c *Client) (*SystemCommandsResponse, error) // SystemExecuteCommandRequest retrieves all configured system commands. type SystemExecuteCommandRequest struct { // Source for which to list commands. - Source CommandSource `json:"source"` + Source dataModels.CommandSource `json:"source"` // Action is the identifier of the command, action from its definition. Action string `json:"action"` @@ -53,7 +62,7 @@ type SystemExecuteCommandRequest struct { // Do sends an API request and returns an error if any. func (cmd *SystemExecuteCommandRequest) Do(c *Client) error { - uri := fmt.Sprintf("%s/%s/%s", URISystemCommands, cmd.Source, cmd.Action) - _, err := c.doJSONRequest("POST", uri, nil, ExecuteErrors) + uri := fmt.Sprintf("%s/%s/%s", SystemCommandsApiUri, cmd.Source, cmd.Action) + _, err := c.doJsonRequest("POST", uri, nil, ExecuteErrors) return err } diff --git a/octoprintApis/system_test.go b/octoprintApis/system_test.go old mode 100644 new mode 100755 index b99cab6d..0d6b6333 --- a/octoprintApis/system_test.go +++ b/octoprintApis/system_test.go @@ -1,5 +1,6 @@ package octoprintApis +/* import ( "testing" @@ -29,3 +30,4 @@ func TestSystemExecuteCommandRequest_Do(t *testing.T) { err = r.Do(cli) assert.NoError(t, err) } +*/ \ No newline at end of file diff --git a/octoprintApis/version.go b/octoprintApis/version.go old mode 100644 new mode 100755 index 1a68a9aa..f1e01202 --- a/octoprintApis/version.go +++ b/octoprintApis/version.go @@ -2,21 +2,25 @@ package octoprintApis import ( "encoding/json" + + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) -const URIVersion = "/api/version" + +const VersionApiUri = "/api/version" + // VersionRequest retrieve information regarding server and API version. type VersionRequest struct{} // Do sends an API request and returns the API response. -func (cmd *VersionRequest) Do(c *Client) (*VersionResponse, error) { - b, err := c.doJSONRequest("GET", URIVersion, nil, nil) +func (cmd *VersionRequest) Do(c *Client) (*dataModels.VersionResponse, error) { + b, err := c.doJsonRequest("GET", VersionApiUri, nil, nil) if err != nil { return nil, err } - r := &VersionResponse{} + r := &dataModels.VersionResponse{} if err := json.Unmarshal(b, r); err != nil { return nil, err } diff --git a/octoprintApis/zbolt.go b/octoprintApis/zbolt.go index b0381637..96559215 100755 --- a/octoprintApis/zbolt.go +++ b/octoprintApis/zbolt.go @@ -1,148 +1,12 @@ package octoprintApis import ( - "bytes" - "encoding/json" - "fmt" - "log" + // "bytes" + // "encoding/json" + // "fmt" + // "log" ) -const URIZBoltRequest = "/api/plugin/zbolt" -const URIZBoltOctoScreenRequest = "/api/plugin/zbolt_octoscreen" -type RunZOffsetCalibrationRequest struct { - Command string `json:"command"` -} - -func (cmd *RunZOffsetCalibrationRequest) Do(c *Client) error { - cmd.Command = "run_zoffset_calibration" - - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(cmd); err != nil { - log.Println("zbolt.Do() 1 - NewEncoder() failed") - return err - } - - _, err := c.doJSONRequest("POST", URIZBoltRequest, b, ConnectionErrors) - return err -} - -// SetZOffsetRequest - retrieves the current configuration of OctoPrint. -type SetZOffsetRequest struct { - Command string `json:"command"` - Tool int `json:"tool"` - Value float64 `json:"value"` -} - -func (cmd *SetZOffsetRequest) Do(c *Client) error { - cmd.Command = "set_z_offset" - - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(cmd); err != nil { - log.Println("zbolt.Do() 2 - Encode() failed") - return err - } - - _, err := c.doJSONRequest("POST", URIZBoltRequest, b, ConnectionErrors) - return err -} - -type GetZOffsetRequest struct { - Command string `json:"command"` - Tool int `json:"tool"` -} - -type GetZOffsetResponse struct { - // Job contains information regarding the target of the current print job. - Offset float64 `json:"offset"` -} - -func (cmd *GetZOffsetRequest) Do(c *Client) (*GetZOffsetResponse, error) { - cmd.Command = "get_z_offset" - - params := bytes.NewBuffer(nil) - if err := json.NewEncoder(params).Encode(cmd); err != nil { - log.Println("zbolt.Do() 3 - Encode() failed") - return nil, err - } - - // b, err := c.doJSONRequest("POST", URIZBoltRequest, params, ConnectionErrors) - b, err := c.doJSONRequest("GET", URIZBoltRequest, params, ConnectionErrors) - if err != nil { - log.Println("zbolt.Do() 3 - doJSONRequest() failed") - return nil, err - } - - r := &GetZOffsetResponse{} - if err := json.Unmarshal(b, r); err != nil { - log.Println("zbolt.Do() 3 - Unmarshal() failed") - return nil, err - } - - return r, err -} - -type GetNotificationRequest struct { - Command string `json:"command"` -} - -type GetNotificationResponse struct { - // Job contains information regarding the target of the current print job. - Message string `json:"message"` -} - -func (cmd *GetNotificationRequest) Do(c *Client) (*GetNotificationResponse, error) { - target := fmt.Sprintf("%s?command=get_notification", URIZBoltOctoScreenRequest) - bytes, err := c.doJSONRequest("GET", target, nil, ConnectionErrors) - if err != nil { - return nil, err - } - - response := &GetNotificationResponse{} - if err := json.Unmarshal(bytes, response); err != nil { - return nil, err - } - - return response, err -} - - -type GetSettingsRequest struct { - Command string `json:"command"` -} - -type MenuItem struct { - Name string `json:"name"` - Icon string `json:"icon"` - Panel string `json:"panel"` - Items []MenuItem `json:"items"` -} - -type GetSettingsResponse struct { - // Job contains information regarding the target of the current print job. - FilamentInLength float64 `json:"filament_in_length"` - FilamentOutLength float64 `json:"filament_out_length"` - ToolChanger bool `json:"toolchanger"` - XAxisInverted bool `json:"x_axis_inverted"` - YAxisInverted bool `json:"y_axis_inverted"` - ZAxisInverted bool `json:"z_axis_inverted"` - MenuStructure []MenuItem `json:"menu_structure"` - GCodes struct { - AutoBedLevel string `json:"auto_bed_level"` - } `json:"gcodes"` -} - -func (cmd *GetSettingsRequest) Do(c *Client) (*GetSettingsResponse, error) { - target := fmt.Sprintf("%s?command=get_settings", URIZBoltOctoScreenRequest) - bytes, err := c.doJSONRequest("GET", target, nil, ConnectionErrors) - if err != nil { - return nil, err - } - - response := &GetSettingsResponse{} - if err := json.Unmarshal(bytes, response); err != nil { - return nil, err - } - - return response, err -} +const PluginZBoltApiUri = "/api/plugin/zbolt" +const PluginZBoltOctoScreenApiUri = "/api/plugin/zbolt_octoscreen" From ae057fcf78e183c6aa9b4bd7ac07751bcda3959a Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 31 Jan 2021 14:08:27 -0800 Subject: [PATCH 27/94] Hard fork of mcuadros/go-octoprint-moved to octoprintApis and octoprintApis/dataModels --- octoprintApis/files_test.go | 88 ----------------------------- octoprintApis/printer_test.go | 100 --------------------------------- octoprintApis/settings_test.go | 19 ------- 3 files changed, 207 deletions(-) delete mode 100755 octoprintApis/files_test.go delete mode 100755 octoprintApis/printer_test.go delete mode 100755 octoprintApis/settings_test.go diff --git a/octoprintApis/files_test.go b/octoprintApis/files_test.go deleted file mode 100755 index 48ddd38c..00000000 --- a/octoprintApis/files_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package octoprintApis - -/* -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestUploadFileRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &UploadFileRequest{Location: Local} - err := r.AddFile("foo.gcode", bytes.NewBufferString("foo")) - assert.NoError(t, err) - - state, err := r.Do(cli) - assert.NoError(t, err) - assert.Equal(t, "foo.gcode", state.File.Local.Name) - - err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) - assert.NoError(t, err) -} - -func TestUploadFileRequest_DoWithFolder(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &UploadFileRequest{Location: Local} - err := r.AddFolder("qux") - assert.NoError(t, err) - - state, err := r.Do(cli) - assert.NoError(t, err) - assert.Equal(t, true, state.Done) -} - -func TestFilesRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - ur := &UploadFileRequest{Location: Local} - err := ur.AddFile("foo.gcode", bytes.NewBufferString("foo")) - assert.NoError(t, err) - - _, err = ur.Do(cli) - assert.NoError(t, err) - - files, err := (&FilesRequest{}).Do(cli) - assert.NoError(t, err) - - assert.True(t, len(files.Files) >= 1) - err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) - assert.NoError(t, err) - return - - r := &FileRequest{Location: Local, Filename: "foo.gcode"} - file, err := r.Do(cli) - assert.NoError(t, err) - - assert.Equal(t, "foo.gcode", file.Name) - - err = (&DeleteFileRequest{Location: Local, Path: "foo.gcode"}).Do(cli) - assert.NoError(t, err) -} - -func TestSelectFileRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - ur := &UploadFileRequest{Location: Local} - err := ur.AddFile("foo2.gcode", bytes.NewBufferString("foo")) - assert.NoError(t, err) - _, err = ur.Do(cli) - assert.NoError(t, err) - - r := &SelectFileRequest{Location: Local, Path: "foo2.gcode"} - err = r.Do(cli) - assert.NoError(t, err) -} - -func xxxTestFilesRequest_DoWithLocation(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - files, err := (&FilesRequest{Location: SDCard}).Do(cli) - assert.NoError(t, err) - - assert.Len(t, files.Files, 0) -} -*/ \ No newline at end of file diff --git a/octoprintApis/printer_test.go b/octoprintApis/printer_test.go deleted file mode 100755 index dd0bf8f5..00000000 --- a/octoprintApis/printer_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package octoprintApis - -/* -import ( - "testing" - "time" - - "github.com/Z-Bolt/OctoScreen/octoprintApis" - "github.com/stretchr/testify/assert" -) - -func TestStateRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &octoprintApis.StateRequest{} - state, err := r.Do(cli) - assert.NoError(t, err) - - assert.Equal(t, "Operational", state.State.Text) - assert.Len(t, state.Temperature.Current, 2) - assert.Len(t, state.Temperature.History, 0) -} - -func TestStateRequest_DoWithHistory(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &octoprintApis.StateRequest{ - IncludeHistory: true, - } - state, err := r.Do(cli) - assert.NoError(t, err) - - assert.Equal(t, "Operational", state.State.Text) - assert.Len(t, state.Temperature.Current, 2) - assert.True(t, len(state.Temperature.History) > 0) -} - -func TestStateRequest_DoWithExclude(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &octoprintApis.StateRequest{Exclude: []string{"temperature"}} - state, err := r.Do(cli) - assert.NoError(t, err) - - assert.Equal(t, "Operational", state.State.Text) - assert.Len(t, state.Temperature.Current, 0) -} - -func TestSDInitRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &SDInitRequest{} - err := r.Do(cli) - assert.NoError(t, err) - - time.Sleep(50 * time.Millisecond) - - state, err := (&SDStateRequest{}).Do(cli) - assert.NoError(t, err) - assert.True(t, state.Ready) -} - -func TestSDReleaseRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &SDReleaseRequest{} - err := r.Do(cli) - assert.NoError(t, err) - - state, err := (&SDStateRequest{}).Do(cli) - assert.NoError(t, err) - assert.False(t, state.Ready) -} - -func TestSDRefreshRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &SDRefreshRequest{} - err := r.Do(cli) - assert.NoError(t, err) - - state, err := (&SDStateRequest{}).Do(cli) - assert.NoError(t, err) - assert.False(t, state.Ready) -} - -func TestCustomCommandsRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &CustomCommandsRequest{} - s, err := r.Do(cli) - assert.NoError(t, err) - - assert.Len(t, s.Controls, 1) - assert.Equal(t, s.Controls[0].Name, "Example for multiple commands") - assert.Len(t, s.Controls[0].Children, 1) - assert.Equal(t, s.Controls[0].Children[0].Name, "Move X (static)") - assert.Len(t, s.Controls[0].Children[0].Commands, 3) -} -*/ \ No newline at end of file diff --git a/octoprintApis/settings_test.go b/octoprintApis/settings_test.go deleted file mode 100755 index 2d67f2a0..00000000 --- a/octoprintApis/settings_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package octoprintApis - -/* -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSettingsRequest_Do(t *testing.T) { - cli := NewClient("http://localhost:5000", "") - - r := &SettingsRequest{} - settings, err := r.Do(cli) - assert.NoError(t, err) - - assert.Equal(t, settings.API.Enabled, true) -} -*/ \ No newline at end of file From b1fae8b46517a30ce7afcc4b61b8d07a9720ee4f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 31 Jan 2021 14:15:04 -0800 Subject: [PATCH 28/94] Hard fork of mcuadros/go-octoprint-updated code to use new octoprintApis package and new dataModels package --- interfaces/ITemperatureDataDisplay.go | 5 +- ui/BedLevelPanel.go | 9 +-- ui/CommonPanel.go | 5 +- ui/ControlPanel.go | 13 ++-- ui/CustomItemsPanel.go | 7 +- ui/FilamentPanel.go | 4 ++ ui/FilesPanel.go | 39 +++++----- ui/HomePanel.go | 9 +-- ui/IdleStatusPanel.go | 3 +- ui/MovePanel.go | 29 ++++---- ui/PrintStatusPanel.go | 17 ++--- ui/TemperaturePresetsPanel.go | 1 + ui/menu.go | 8 ++- ui/tool_changer_panel.go | 1 + ui/ui.go | 20 +++--- ui/z_offset_calibration_panel.go | 3 +- uiWidgets/CommandButton.go | 7 +- uiWidgets/ControlButton.go | 5 +- uiWidgets/CoolDownButton.go | 2 +- uiWidgets/FanButton.go | 1 + uiWidgets/FilamentExtrudeButton.go | 42 ++++------- uiWidgets/FilamentLoadButton.go | 42 +++++------ uiWidgets/FlowRateStepButton.go | 12 +--- uiWidgets/HomeAllButton.go | 11 +-- uiWidgets/HomeButton.go | 5 +- uiWidgets/MoveButton.go | 11 +-- uiWidgets/OctoPrintInfoBox.go | 5 +- uiWidgets/OctoScreenInfoBox.go | 1 + uiWidgets/OctoScreenPluginInfoBox.go | 7 +- uiWidgets/SelectToolStepButton.go | 1 + uiWidgets/SystemCommandButton.go | 5 +- uiWidgets/SystemInfoBox.go | 1 + uiWidgets/TemperatureIncreaseButton.go | 1 + uiWidgets/TemperaturePresetButton.go | 5 +- uiWidgets/TemperatureStatusBox.go | 5 +- uiWidgets/ToolButton.go | 4 +- .../{background_task.go => BackgroundTask.go} | 1 + utils/FileResponsesSortedByDate.go | 7 +- utils/FileResponsesSortedByName.go | 7 +- utils/LocationHistory.go | 10 +-- utils/UpdateTemperaturesBackgroundTask.go | 4 +- utils/environment.go | 12 ++++ utils/filament.go | 71 +++++++++++++++++++ utils/file_utils.go | 23 +++++- utils/tools.go | 60 ++++++++++++---- utils/ui_utils.go | 27 ++++--- 46 files changed, 360 insertions(+), 208 deletions(-) rename utils/{background_task.go => BackgroundTask.go} (99%) create mode 100755 utils/filament.go diff --git a/interfaces/ITemperatureDataDisplay.go b/interfaces/ITemperatureDataDisplay.go index 9ac7c922..adca6fe8 100755 --- a/interfaces/ITemperatureDataDisplay.go +++ b/interfaces/ITemperatureDataDisplay.go @@ -1,9 +1,10 @@ package interfaces import ( - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) type ITemperatureDataDisplay interface { - UpdateTemperatureData(temperatureData map[string]octoprintApis.TemperatureData) + UpdateTemperatureData(temperatureData map[string]dataModels.TemperatureData) } diff --git a/ui/BedLevelPanel.go b/ui/BedLevelPanel.go index 7f608cbc..d4f1fb94 100755 --- a/ui/BedLevelPanel.go +++ b/ui/BedLevelPanel.go @@ -6,6 +6,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -106,17 +107,17 @@ func (this *bedLevelPanel) addBedLevelCornerButton(isLeft, isTop bool) { func (this *bedLevelPanel) defineLevelingPoints() { utils.Logger.Debug("entering BedLevelPanel.verifyConnection()") - connectionRequest, err := (&octoprintApis.ConnectionRequest{}).Do(this.UI.Client) + connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(ConnectionRequest)", err) + utils.LogError("BedLevelPanel.defineLevelingPoints()", "version.Get()", err) utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()") return } - utils.Logger.Info(connectionRequest.Current.PrinterProfile) + utils.Logger.Info(connectionResponse.Current.PrinterProfile) - printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionRequest.Current.PrinterProfile}).Do(this.UI.Client) + printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(this.UI.Client) if err != nil { utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(PrinterProfilesRequest)", err) diff --git a/ui/CommonPanel.go b/ui/CommonPanel.go index ab40fbc3..0dd2a122 100755 --- a/ui/CommonPanel.go +++ b/ui/CommonPanel.go @@ -11,11 +11,12 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) // OctoScreenVersion - set at compilation time. -var OctoScreenVersion = "2.6.1" +var OctoScreenVersion = "2.7.0" type CommonPanel struct { UI *UI @@ -106,7 +107,7 @@ func (this *CommonPanel) Scaled(s int) int { func (this *CommonPanel) arrangeMenuItems( grid *gtk.Grid, - items []octoprintApis.MenuItem, + items []dataModels.MenuItem, cols int, ) { for i, item := range items { diff --git a/ui/ControlPanel.go b/ui/ControlPanel.go index f7370cf0..de4667b6 100755 --- a/ui/ControlPanel.go +++ b/ui/ControlPanel.go @@ -5,8 +5,9 @@ import ( // "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" - "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/uiWidgets" + "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -51,8 +52,8 @@ func (this *controlPanel) initialize() { } } -func (this *controlPanel) getDefaultControls() []*octoprintApis.ControlDefinition { - var controlDefinitions = []*octoprintApis.ControlDefinition{{ +func (this *controlPanel) getDefaultControls() []*dataModels.ControlDefinition { + var controlDefinitions = []*dataModels.ControlDefinition{{ Name: "Motor Off", Command: "M18", // Disable all stepper motors immediately }, { @@ -69,8 +70,8 @@ func (this *controlPanel) getDefaultControls() []*octoprintApis.ControlDefinitio return controlDefinitions } -func (this *controlPanel) getCustomControls() []*octoprintApis.ControlDefinition { - controlDefinitions := []*octoprintApis.ControlDefinition{} +func (this *controlPanel) getCustomControls() []*dataModels.ControlDefinition { + controlDefinitions := []*dataModels.ControlDefinition{} utils.Logger.Info("control.getCustomControl() - Retrieving custom controls") response, err := (&octoprintApis.CustomCommandsRequest{}).Do(this.UI.Client) @@ -90,7 +91,7 @@ func (this *controlPanel) getCustomControls() []*octoprintApis.ControlDefinition return controlDefinitions } -func (this *controlPanel) getCommands() []*octoprintApis.CommandDefinition { +func (this *controlPanel) getCommands() []*dataModels.CommandDefinition { utils.Logger.Info("Retrieving custom commands") response, err := (&octoprintApis.SystemCommandsRequest{}).Do(this.UI.Client) if err != nil { diff --git a/ui/CustomItemsPanel.go b/ui/CustomItemsPanel.go index 2572f26a..fb39399f 100755 --- a/ui/CustomItemsPanel.go +++ b/ui/CustomItemsPanel.go @@ -2,19 +2,20 @@ package ui import ( "github.com/Z-Bolt/OctoScreen/interfaces" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) type customItemsPanel struct { CommonPanel - items []octoprintApis.MenuItem + items []dataModels.MenuItem } func CustomItemsPanel( ui *UI, parentPanel interfaces.IPanel, - items []octoprintApis.MenuItem, + items []dataModels.MenuItem, ) *customItemsPanel { instance := &customItemsPanel { CommonPanel: NewCommonPanel(ui, parentPanel), diff --git a/ui/FilamentPanel.go b/ui/FilamentPanel.go index b66686f6..66092bc3 100755 --- a/ui/FilamentPanel.go +++ b/ui/FilamentPanel.go @@ -86,8 +86,10 @@ func (this *filamentPanel) initialize() { this.filamentLoadButton = uiWidgets.CreateFilamentLoadButton( this.UI.window, this.UI.Client, + this.flowRateStepButton, this.selectToolStepButton, true, + int(this.UI.Settings.FilamentInLength), // jab revisit ) this.Grid().Attach(this.filamentLoadButton, 0, 1, 1, 1) @@ -97,8 +99,10 @@ func (this *filamentPanel) initialize() { this.filamentUnloadButton = uiWidgets.CreateFilamentLoadButton( this.UI.window, this.UI.Client, + this.flowRateStepButton, this.selectToolStepButton, false, + int(this.UI.Settings.FilamentOutLength), // jab revisit ) this.Grid().Attach(this.filamentUnloadButton, 3, 1, 1, 1) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 962a741d..05b3289f 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -10,6 +10,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" // "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -29,7 +30,7 @@ func FilesPanel( ) *filesPanel { if filesPanelInstance == nil { locationHistory := utils.LocationHistory { - Locations: []octoprintApis.Location{}, + Locations: []dataModels.Location{}, } instance := &filesPanel { @@ -106,8 +107,8 @@ func (this *filesPanel) doLoadFiles() { this.listBox.ShowAll() } -func (this *filesPanel) getSortedFiles() []*octoprintApis.FileResponse { - var files []*octoprintApis.FileResponse +func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { + var files []*dataModels.FileResponse length := this.locationHistory.Length() if length < 1 { @@ -124,12 +125,12 @@ func (this *filesPanel) getSortedFiles() []*octoprintApis.FileResponse { filesResponse, err := filesRequest.Do(this.UI.Client) if err != nil { utils.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) - files = []*octoprintApis.FileResponse{} + files = []*dataModels.FileResponse{} } else { files = filesResponse.Files } - var filteredFiles []*octoprintApis.FileResponse + var filteredFiles []*dataModels.FileResponse for i := range files { if !strings.HasPrefix(files[i].Path, "trash") { filteredFiles = append(filteredFiles, files[i]) @@ -145,8 +146,8 @@ func (this *filesPanel) getSortedFiles() []*octoprintApis.FileResponse { func (this *filesPanel) addRootLocations() { this.addMessage("Select source location:") - this.addRootLocation(octoprintApis.Local, 0) - this.addRootLocation(octoprintApis.SDCard, 1) + this.addRootLocation(dataModels.Local, 0) + this.addRootLocation(dataModels.SDCard, 1) } func (this *filesPanel) addMessage(message string) { @@ -165,9 +166,9 @@ func (this *filesPanel) addMessage(message string) { this.listBox.Add(listItemFrame) } -func (this *filesPanel) addRootLocation(location octoprintApis.Location, index int) { +func (this *filesPanel) addRootLocation(location dataModels.Location, index int) { var itemImage *gtk.Image - if location == octoprintApis.Local { + if location == dataModels.Local { itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) } else { itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35)) @@ -177,7 +178,7 @@ func (this *filesPanel) addRootLocation(location octoprintApis.Location, index i topBox.Add(itemImage) name := "" - if location == octoprintApis.Local { + if location == dataModels.Local { name = " OctoPrint" } else { name = " SD Card" @@ -193,7 +194,7 @@ func (this *filesPanel) addRootLocation(location octoprintApis.Location, index i var itemButton *gtk.Button - if location == octoprintApis.Local { + if location == dataModels.Local { itemButton = this.createOpenLocationButton(location) } else { itemButton = this.createOpenLocationButton(location) @@ -212,7 +213,7 @@ func (this *filesPanel) addRootLocation(location octoprintApis.Location, index i this.listBox.Add(listItemFrame) } -func (this *filesPanel) addSortedFiles(sortedFiles []*octoprintApis.FileResponse) { +func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) { var index int = 0 for _, fileResponse := range sortedFiles { @@ -231,7 +232,7 @@ func (this *filesPanel) addSortedFiles(sortedFiles []*octoprintApis.FileResponse } -func (this *filesPanel) addItem(fileResponse *octoprintApis.FileResponse, index int) { +func (this *filesPanel) addItem(fileResponse *dataModels.FileResponse, index int) { isFolder := fileResponse.IsFolder() var itemImage *gtk.Image @@ -332,7 +333,7 @@ func (this *filesPanel) createListItemBox() *gtk.Box { return listItemBox } -func (this *filesPanel) addThumbnail(fileResponse *octoprintApis.FileResponse, listItemBox *gtk.Box) { +func (this *filesPanel) addThumbnail(fileResponse *dataModels.FileResponse, listItemBox *gtk.Box) { if fileResponse.Thumbnail != "" { utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) @@ -365,11 +366,11 @@ func (this *filesPanel) addThumbnail(fileResponse *octoprintApis.FileResponse, l } -func (this *filesPanel) createOpenLocationButton(location octoprintApis.Location) *gtk.Button { +func (this *filesPanel) createOpenLocationButton(location dataModels.Location) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { this.locationHistory = utils.LocationHistory { - Locations: []octoprintApis.Location{location}, + Locations: []dataModels.Location{location}, } this.doLoadFiles() @@ -382,7 +383,7 @@ func (this *filesPanel) createOpenLocationButton(location octoprintApis.Location return button } -func (this *filesPanel) createOpenFolderButton(fileResponse *octoprintApis.FileResponse) *gtk.Button { +func (this *filesPanel) createOpenFolderButton(fileResponse *dataModels.FileResponse) *gtk.Button { image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) button := utils.MustButton(image, func() { this.locationHistory.GoForward(fileResponse.Name) @@ -396,7 +397,7 @@ func (this *filesPanel) createOpenFolderButton(fileResponse *octoprintApis.FileR return button } -func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *octoprintApis.FileResponse) *gtk.Button { +func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *dataModels.FileResponse) *gtk.Button { button := utils.MustButton( utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { @@ -425,7 +426,7 @@ func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileRespo /* func (this *filesPanel) isReady() bool { - state, err := (&octoprintApis.SDStateRequest{}).Do(this.UI.Client) + state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client) if err != nil { Logger.Error(err) return false diff --git a/ui/HomePanel.go b/ui/HomePanel.go index 374f8e78..5b264738 100755 --- a/ui/HomePanel.go +++ b/ui/HomePanel.go @@ -3,7 +3,8 @@ package ui import ( // "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" // "github.com/Z-Bolt/OctoScreen/utils" ) @@ -32,13 +33,13 @@ func HomePanel( func (this *homePanel) initialize() { defer this.Initialize() - homeXButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home X", "home-x.svg", octoprintApis.XAxis) + homeXButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home X", "home-x.svg", dataModels.XAxis) this.Grid().Attach(homeXButton, 2, 1, 1, 1) - homeYButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Y", "home-y.svg", octoprintApis.YAxis) + homeYButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Y", "home-y.svg", dataModels.YAxis) this.Grid().Attach(homeYButton, 1, 0, 1, 1) - homeZButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Z", "home-z.svg", octoprintApis.ZAxis) + homeZButton := uiWidgets.CreateHomeButton(this.UI.Client, "Home Z", "home-z.svg", dataModels.ZAxis) this.Grid().Attach(homeZButton, 1, 1, 1, 1) homeAllButton := uiWidgets.CreateHomeAllButton(this.UI.Client) diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go index 9d91caaf..64721701 100755 --- a/ui/IdleStatusPanel.go +++ b/ui/IdleStatusPanel.go @@ -6,6 +6,7 @@ import ( "time" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -41,7 +42,7 @@ func (this *idleStatusPanel) initialize() { utils.Logger.Info(this.UI.Settings) - var menuItems []octoprintApis.MenuItem + var menuItems []dataModels.MenuItem if this.UI.Settings == nil || this.UI.Settings.MenuStructure == nil || len(this.UI.Settings.MenuStructure) < 1 { utils.Logger.Info("Loading default menu") this.UI.Settings.MenuStructure = getDefaultMenuItems(this.UI.Client) diff --git a/ui/MovePanel.go b/ui/MovePanel.go index 29f874a1..f4398d8c 100755 --- a/ui/MovePanel.go +++ b/ui/MovePanel.go @@ -1,9 +1,12 @@ package ui import ( + // "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" + // "github.com/Z-Bolt/OctoScreen/utils" ) var movePanelInstance *movePanel @@ -42,27 +45,27 @@ func (this *movePanel) initialize() { } if xAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprintApis.XAxis, 1), 0, 1, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprintApis.XAxis, -1), 2, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", dataModels.XAxis, 1), 0, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", dataModels.XAxis, -1), 2, 1, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", octoprintApis.XAxis, -1), 0, 1, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", octoprintApis.XAxis, 1), 2, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X-", "move-x-.svg", dataModels.XAxis, -1), 0, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "X+", "move-x+.svg", dataModels.XAxis, 1), 2, 1, 1, 1) } if yAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprintApis.YAxis, -1), 1, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprintApis.YAxis, 1), 1, 2, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", dataModels.YAxis, -1), 1, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", dataModels.YAxis, 1), 1, 2, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", octoprintApis.YAxis, 1), 1, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", octoprintApis.YAxis, -1), 1, 2, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y+", "move-y+.svg", dataModels.YAxis, 1), 1, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Y-", "move-y-.svg", dataModels.YAxis, -1), 1, 2, 1, 1) } if zAxisInverted { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprintApis.ZAxis, -1), 3, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprintApis.ZAxis, 1), 3, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", dataModels.ZAxis, -1), 3, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", dataModels.ZAxis, 1), 3, 1, 1, 1) } else { - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", octoprintApis.ZAxis, 1), 3, 0, 1, 1) - this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", octoprintApis.ZAxis, -1), 3, 1, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z+", "move-z+.svg", dataModels.ZAxis, 1), 3, 0, 1, 1) + this.Grid().Attach(uiWidgets.CreateMoveButton(this.UI.Client, this.amountToMoveStepButton, "Z-", "move-z-.svg", dataModels.ZAxis, -1), 3, 1, 1, 1) } this.Grid().Attach(this.amountToMoveStepButton, 1, 1, 1, 1) diff --git a/ui/PrintStatusPanel.go b/ui/PrintStatusPanel.go index 3143a7d0..17084e1c 100755 --- a/ui/PrintStatusPanel.go +++ b/ui/PrintStatusPanel.go @@ -6,11 +6,13 @@ import ( "time" "github.com/gotk3/gotk3/gtk" - "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) + var printStatusPanelInstance *printStatusPanel type printStatusPanel struct { @@ -39,7 +41,7 @@ func PrintStatusPanel(ui *UI) *printStatusPanel { CommonPanel: NewTopLevelCommonPanel(ui, nil), } - // TODO: revisit... some set the background task and the initialize + // TODO: revisit... some set the background task and then initialize // and others initialize and then set the background task instance.backgroundTask = utils.CreateBackgroundTask(time.Second * 2, instance.update) instance.initialize() @@ -157,7 +159,7 @@ func (this *printStatusPanel) createPauseButton() gtk.IWidget { defer this.updateTemperature() utils.Logger.Info("Pausing/Resuming job") - cmd := &octoprintApis.PauseRequest{Action: octoprintApis.Toggle} + cmd := &octoprintApis.PauseRequest{Action: dataModels.Toggle} err := cmd.Do(this.UI.Client) utils.Logger.Info("Pausing/Resuming job 2, Do() was just called") @@ -238,7 +240,7 @@ func (this *printStatusPanel) updateTemperature() { //Logger.Printf("Now leaving print_status.updateTemperature()") } -func (this *printStatusPanel) doUpdateState(printerState *octoprintApis.PrinterState) { +func (this *printStatusPanel) doUpdateState(printerState *dataModels.PrinterState) { switch { case printerState.Flags.Printing: this.pauseButton.SetSensitive(true) @@ -308,17 +310,12 @@ func (this *printStatusPanel) updateJob() { if jobResponse.Job.File.Name != "" { jobFileName = jobResponse.Job.File.Name jobFileName = strings.Replace(jobFileName, ".gcode", "", -1) + jobFileName = strings.Replace(jobFileName, ".gco", "", -1) jobFileName = utils.TruncateString(jobFileName, 20) } this.fileLabel.Label.SetLabel(jobFileName) this.progressBar.SetFraction(jobResponse.Progress.Completion / 100) - // strProgress := fmd.Sprintf("%d%% L=%d/%d", - // jobResponse.Progress.Completion / 100, - // jobResponse.Progress, - // ) - // this.progressBar.SetText(strProgress) - var timeSpent, timeLeft string switch jobResponse.Progress.Completion { diff --git a/ui/TemperaturePresetsPanel.go b/ui/TemperaturePresetsPanel.go index 9ace3414..a335cefe 100755 --- a/ui/TemperaturePresetsPanel.go +++ b/ui/TemperaturePresetsPanel.go @@ -3,6 +3,7 @@ package ui import ( "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/ui/menu.go b/ui/menu.go index da7d8119..594edae6 100755 --- a/ui/menu.go +++ b/ui/menu.go @@ -5,13 +5,15 @@ import ( "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) func getPanel( ui *UI, parentPanel interfaces.IPanel, - menuItem octoprintApis.MenuItem, + menuItem dataModels.MenuItem, ) interfaces.IPanel { switch menuItem.Panel { // The standard "top four" panels that are in the idleStatus panel @@ -98,7 +100,7 @@ func getPanel( } } -func getDefaultMenuItems(client *octoprintApis.Client) []octoprintApis.MenuItem { +func getDefaultMenuItems(client *octoprintApis.Client) []dataModels.MenuItem { defaultMenuItemsForSingleToolhead := `[ { "name": "Home", @@ -205,7 +207,7 @@ func getDefaultMenuItems(client *octoprintApis.Client) []octoprintApis.MenuItem ]` - var menuItems []octoprintApis.MenuItem + var menuItems []dataModels.MenuItem var err error toolheadCount := utils.GetToolheadCount(client) diff --git a/ui/tool_changer_panel.go b/ui/tool_changer_panel.go index 627eb326..817ca664 100755 --- a/ui/tool_changer_panel.go +++ b/ui/tool_changer_panel.go @@ -6,6 +6,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/ui/ui.go b/ui/ui.go index dd6c5887..16200bb0 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -12,17 +12,19 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) + type UI struct { sync.Mutex PanelHistory *stack.Stack Client *octoprintApis.Client - ConnectionState octoprintApis.ConnectionState - Settings *octoprintApis.GetSettingsResponse + ConnectionState dataModels.ConnectionState + Settings *dataModels.OctoScreenSettingsResponse UIState string @@ -269,7 +271,7 @@ func (this *UI) checkNotification() { return } - notificationRespone, err := (&octoprintApis.GetNotificationRequest{}).Do(this.Client) + notificationRespone, err := (&octoprintApis.NotificationRequest{}).Do(this.Client) if err != nil { utils.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) utils.Logger.Debug("leaving ui.checkNotification()") @@ -286,7 +288,7 @@ func (this *UI) checkNotification() { func (this *UI) loadSettings() { utils.Logger.Debug("entering ui.loadSettings()") - settingsResponse, err := (&octoprintApis.GetSettingsRequest{}).Do(this.Client) + settingsResponse, err := (&octoprintApis.OctoScreenSettingsRequest{}).Do(this.Client) if err != nil { text := err.Error() if strings.Contains(strings.ToLower(text), "unexpected status code: 404") { @@ -294,7 +296,7 @@ func (this *UI) loadSettings() { // OctoScreen plug-in is available. If calling GetSettings returns // a 404, the plug-in isn't available. this.OctoPrintPluginIsAvailable = false - utils.Logger.Info("The OctoPrint plug-in is not available") + utils.Logger.Info("The OctoScreen plug-in is not available") } else { // If we get back any other kind of error, something bad happened, so log an error. utils.LogError("ui.loadSettings()", "Do(GetSettingsRequest)", err) @@ -315,7 +317,7 @@ func (this *UI) loadSettings() { utils.Logger.Debug("leaving ui.loadSettings()") } -func (this *UI) validateMenuItems(menuItems []octoprintApis.MenuItem, name string, isRoot bool) bool { +func (this *UI) validateMenuItems(menuItems []dataModels.MenuItem, name string, isRoot bool) bool { if menuItems == nil { return true } @@ -380,9 +382,9 @@ func (this *UI) update() { this.loadSettings() if this.Settings == nil { - this.Settings = &octoprintApis.GetSettingsResponse { - FilamentInLength: 750.0, - FilamentOutLength: 800.0, + this.Settings = &dataModels.OctoScreenSettingsResponse { + FilamentInLength: 100, + FilamentOutLength: 100, ToolChanger: false, XAxisInverted: false, YAxisInverted: false, diff --git a/ui/z_offset_calibration_panel.go b/ui/z_offset_calibration_panel.go index 425623ee..fddc7a1e 100755 --- a/ui/z_offset_calibration_panel.go +++ b/ui/z_offset_calibration_panel.go @@ -8,6 +8,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -114,7 +115,7 @@ func (this *zOffsetCalibrationPanel) selectToolStepButtonHandleClick() { time.Sleep(time.Second * 1) this.command(fmt.Sprintf("G0 X%f Y%f F10000", this.cPoint.x, this.cPoint.y)) - cmd := &octoprintApis.GetZOffsetRequest{Tool: this.activeTool} + cmd := &octoprintApis.ZOffsetRequest{Tool: this.activeTool} response, err := cmd.Do(this.UI.Client) if err != nil { utils.LogError("z_offset_calibration.setToolheadButtonClickHandler()", "Do(GetZOffsetRequest)", err) diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index 91e7dacc..0db7cfaa 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,13 +14,13 @@ type CommandButton struct { client *octoprintApis.Client parentWindow *gtk.Window - commandDefinition *octoprintApis.CommandDefinition + commandDefinition *dataModels.CommandDefinition } func CreateCommandButton( client *octoprintApis.Client, parentWindow *gtk.Window, - commandDefinition *octoprintApis.CommandDefinition, + commandDefinition *dataModels.CommandDefinition, iconName string, ) *CommandButton { base := utils.MustButtonImage(utils.StrEllipsisLen(commandDefinition.Name, 16), iconName + ".svg", nil) @@ -48,7 +49,7 @@ func (this *CommandButton) handleClicked() { func (this *CommandButton) sendCommand() { commandRequest := &octoprintApis.SystemExecuteCommandRequest{ - Source: octoprintApis.Custom, + Source: dataModels.Custom, Action: this.commandDefinition.Action, } diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index 5f8a0ec1..a765376f 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -13,13 +14,13 @@ type ControlButton struct { client *octoprintApis.Client parentWindow *gtk.Window - controlDefinition *octoprintApis.ControlDefinition + controlDefinition *dataModels.ControlDefinition } func CreateControlButton( client *octoprintApis.Client, parentWindow *gtk.Window, - controlDefinition *octoprintApis.ControlDefinition, + controlDefinition *dataModels.ControlDefinition, iconName string, ) *ControlButton { base := utils.MustButtonImage(utils.StrEllipsisLen(controlDefinition.Name, 16), iconName + ".svg", nil) diff --git a/uiWidgets/CoolDownButton.go b/uiWidgets/CoolDownButton.go index b6198aec..f306c354 100755 --- a/uiWidgets/CoolDownButton.go +++ b/uiWidgets/CoolDownButton.go @@ -5,10 +5,10 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) - type CoolDownButton struct { *gtk.Button diff --git a/uiWidgets/FanButton.go b/uiWidgets/FanButton.go index d5a033a2..24ca50eb 100755 --- a/uiWidgets/FanButton.go +++ b/uiWidgets/FanButton.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/FilamentExtrudeButton.go b/uiWidgets/FilamentExtrudeButton.go index df434f07..05415ab4 100755 --- a/uiWidgets/FilamentExtrudeButton.go +++ b/uiWidgets/FilamentExtrudeButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -53,37 +54,20 @@ func (this *FilamentExtrudeButton) handleClicked() { this.sendExtrudeCommand(this.amountToExtrudeStepButton.Value()) } -func (this *FilamentExtrudeButton) sendExtrudeCommand(amount int) { - // The flow rate step button is optional. - if this.flowRateStepButton != nil { - err := this.flowRateStepButton.SendChangeFlowRate() - if err != nil { - utils.LogError("FilamentExtrudeButton.sendExtrudeCommand()", "SendChangeFlowRate()", err) - return - } - } - +func (this *FilamentExtrudeButton) sendExtrudeCommand(length int) { extruderId := this.selectToolStepButton.Value() - var action string - if this.isForward { - action = "extrude" - } else { - action = "retract" - } - if utils.CurrentHotendTemperatureIsTooLow(this.client, extruderId, action, this.parentWindow) { - utils.Logger.Error("FilamentExtrudeButton.sendExtrudeCommand() - temperature is too low") - return - } - cmd := &octoprintApis.ToolExtrudeRequest{} - if this.isForward { - cmd.Amount = amount - } else { - cmd.Amount = -amount + flowRatePercentage := 100 + if this.flowRateStepButton != nil { + flowRatePercentage = this.flowRateStepButton.Value() } - utils.Logger.Infof("FilamentExtrudeButton.sendExtrudeCommand() - sending extrude request with amount: %d", cmd.Amount) - if err := cmd.Do(this.client); err != nil { - utils.LogError("FilamentExtrudeButton.sendExtrudeCommand()", "Do(ToolExtrudeRequest)", err) - } + utils.Extrude( + this.client, + this.isForward, + extruderId, + this.parentWindow, + flowRatePercentage, + length, + ) } diff --git a/uiWidgets/FilamentLoadButton.go b/uiWidgets/FilamentLoadButton.go index 47bd1309..dadce415 100755 --- a/uiWidgets/FilamentLoadButton.go +++ b/uiWidgets/FilamentLoadButton.go @@ -1,25 +1,33 @@ package uiWidgets import ( + // "fmt" + "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) + type FilamentLoadButton struct { *gtk.Button parentWindow *gtk.Window client *octoprintApis.Client + flowRateStepButton *FlowRateStepButton // The flow rate step button is optional. selectToolStepButton *SelectToolStepButton isForward bool + length int } func CreateFilamentLoadButton( parentWindow *gtk.Window, client *octoprintApis.Client, + flowRateStepButton *FlowRateStepButton, // The flow rate step button is optional. selectToolStepButton *SelectToolStepButton, isForward bool, + length int, ) *FilamentLoadButton { var base *gtk.Button if isForward { @@ -32,8 +40,10 @@ func CreateFilamentLoadButton( Button: base, parentWindow: parentWindow, client: client, + flowRateStepButton: flowRateStepButton, selectToolStepButton: selectToolStepButton, isForward: isForward, + length: length, } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { @@ -49,28 +59,18 @@ func (this *FilamentLoadButton) handleClicked() { func (this *FilamentLoadButton) sendLoadCommand() { extruderId := this.selectToolStepButton.Value() - var action string - if this.isForward { - action = "load" - } else { - action = "unload" - } - if utils.CurrentHotendTemperatureIsTooLow(this.client, extruderId, action, this.parentWindow) { - utils.Logger.Error("FilamentLoadButton.sendLoadCommand() - temperature is too low") - return - } - // BUG: This does not work. At least not on a Prusa i3. Need to get this working with all printers. - cmd := &octoprintApis.CommandRequest{} - if this.isForward { - cmd.Commands = []string{"G91", "G0 E600 F5000", "G0 E120 F500", "G90"} - } else { - cmd.Commands = []string{"G91", "G0 E-800 F5000", "G90"} + flowRatePercentage := 100 + if this.flowRateStepButton != nil { + flowRatePercentage = this.flowRateStepButton.Value() } - utils.Logger.Info("FilamentLoadButton.sendLoadCommand() - sending filament load request") - if err := cmd.Do(this.client); err != nil { - utils.LogError("FilamentLoadButton.sendLoadCommand()", "Do(CommandRequest)", err) - return - } + utils.Extrude( + this.client, + this.isForward, + extruderId, + this.parentWindow, + flowRatePercentage, + this.length, + ) } diff --git a/uiWidgets/FlowRateStepButton.go b/uiWidgets/FlowRateStepButton.go index 38a07760..36deefc7 100755 --- a/uiWidgets/FlowRateStepButton.go +++ b/uiWidgets/FlowRateStepButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -36,14 +37,5 @@ func (this *FlowRateStepButton) Value() int { } func (this *FlowRateStepButton) SendChangeFlowRate() error { - cmd := &octoprintApis.ToolFlowRateRequest{} - cmd.Factor = this.Value() - - utils.Logger.Infof("FlowRateStepButton.SendChangeFlowRate() - changing flow rate to %d%%", cmd.Factor) - if err := cmd.Do(this.client); err != nil { - utils.LogError("FlowRateStepButton.SendChangeFlowRate()", "Go(ToolFlowRateRequest)", err) - return err - } - - return nil + return utils.SetFlowRate(this.client, this.Value()) } diff --git a/uiWidgets/HomeAllButton.go b/uiWidgets/HomeAllButton.go index e23391d0..1c270d9b 100755 --- a/uiWidgets/HomeAllButton.go +++ b/uiWidgets/HomeAllButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -33,10 +34,10 @@ func (this *HomeAllButton) handleClicked() { utils.Logger.Infof("Homing the print head") // Version A: - axes := []octoprintApis.Axis { - octoprintApis.XAxis, - octoprintApis.YAxis, - octoprintApis.ZAxis, + axes := []dataModels.Axis { + dataModels.XAxis, + dataModels.YAxis, + dataModels.ZAxis, } cmd := &octoprintApis.PrintHeadHomeRequest{Axes: axes} err := cmd.Do(this.client); @@ -47,7 +48,7 @@ func (this *HomeAllButton) handleClicked() { /* // If there are issues with version A, there's also version B: - cmd := &octoprintApis.CommandRequest{} + cmd := &octoprint.CommandRequest{} cmd.Commands = []string{ "G28 Z", "G28 X", diff --git a/uiWidgets/HomeButton.go b/uiWidgets/HomeButton.go index 2ce45ffe..83ce0764 100755 --- a/uiWidgets/HomeButton.go +++ b/uiWidgets/HomeButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -10,14 +11,14 @@ type HomeButton struct { *gtk.Button client *octoprintApis.Client - axes []octoprintApis.Axis + axes []dataModels.Axis } func CreateHomeButton( client *octoprintApis.Client, buttonLabel string, imageFileName string, - axes ...octoprintApis.Axis, + axes ...dataModels.Axis, ) *HomeButton { base := utils.MustButtonImageStyle(buttonLabel, imageFileName, "", nil) diff --git a/uiWidgets/MoveButton.go b/uiWidgets/MoveButton.go index 7a5b2dd3..84475978 100755 --- a/uiWidgets/MoveButton.go +++ b/uiWidgets/MoveButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -11,7 +12,7 @@ type MoveButton struct { client *octoprintApis.Client amountToMoveStepButton *AmountToMoveStepButton - axis octoprintApis.Axis + axis dataModels.Axis direction float64 } @@ -20,7 +21,7 @@ func CreateMoveButton( amountToMoveStepButton *AmountToMoveStepButton, label string, image string, - axis octoprintApis.Axis, + axis dataModels.Axis, direction float64, ) *MoveButton { // A little bit of a "chicken or the egg" situation here. Create the @@ -43,13 +44,13 @@ func (this *MoveButton) handlePressed() { distance := this.amountToMoveStepButton.Value() * this.direction cmd := &octoprintApis.PrintHeadJogRequest{} switch this.axis { - case octoprintApis.XAxis: + case dataModels.XAxis: cmd.X = distance - case octoprintApis.YAxis: + case dataModels.YAxis: cmd.Y = distance - case octoprintApis.ZAxis: + case dataModels.ZAxis: cmd.Z = distance } diff --git a/uiWidgets/OctoPrintInfoBox.go b/uiWidgets/OctoPrintInfoBox.go index 6a252a38..e22ea076 100755 --- a/uiWidgets/OctoPrintInfoBox.go +++ b/uiWidgets/OctoPrintInfoBox.go @@ -2,8 +2,10 @@ package uiWidgets import ( "fmt" + // "log" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -21,6 +23,7 @@ func CreateOctoPrintInfoBox( versionResponse, err := (&octoprintApis.VersionRequest{}).Do(client) if err != nil { + // TODO: should the error really trigger a panic? panic(err) } @@ -29,7 +32,7 @@ func CreateOctoPrintInfoBox( logoImage, "OctoPrint", versionResponse.Server, - fmt.Sprintf("(API %s)", versionResponse.API), + fmt.Sprintf("(API %s)", versionResponse.API), // Use 3 spaces... 1 space doesn't have enough kerning. ) instance := &OctoPrintInfoBox { diff --git a/uiWidgets/OctoScreenInfoBox.go b/uiWidgets/OctoScreenInfoBox.go index d502e179..fac22708 100755 --- a/uiWidgets/OctoScreenInfoBox.go +++ b/uiWidgets/OctoScreenInfoBox.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/OctoScreenPluginInfoBox.go b/uiWidgets/OctoScreenPluginInfoBox.go index 427e4bb9..fd075deb 100755 --- a/uiWidgets/OctoScreenPluginInfoBox.go +++ b/uiWidgets/OctoScreenPluginInfoBox.go @@ -4,6 +4,7 @@ import ( // "fmt" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -20,14 +21,14 @@ func CreateOctoScreenPluginInfoBox( str2 := "" if octoPrintPluginIsInstalled { - getPluginManagerInfoResponse, err := (&octoprintApis.GetPluginManagerInfoRequest{}).Do(client) + pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client) if err != nil { panic(err) } found := false - for i := 0; i < len(getPluginManagerInfoResponse.Plugins) && !found; i++ { - plugin := getPluginManagerInfoResponse.Plugins[i] + for i := 0; i < len(pluginManagerInfoResponse.Plugins) && !found; i++ { + plugin := pluginManagerInfoResponse.Plugins[i] if plugin.Key == "zbolt_octoscreen" { found = true str2 = plugin.Version diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index a2833a13..69c942eb 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/SystemCommandButton.go b/uiWidgets/SystemCommandButton.go index e29bc071..c80f9a49 100755 --- a/uiWidgets/SystemCommandButton.go +++ b/uiWidgets/SystemCommandButton.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -24,7 +25,7 @@ func CreateSystemCommandButton( panic(err) } - var cmd *octoprintApis.CommandDefinition + var cmd *dataModels.CommandDefinition var cb func() for _, commandDefinition := range systemCommandsResponse.Core { @@ -36,7 +37,7 @@ func CreateSystemCommandButton( if cmd != nil { do := func() { systemExecuteCommandRequest := &octoprintApis.SystemExecuteCommandRequest{ - Source: octoprintApis.Core, + Source: dataModels.Core, Action: cmd.Action, } diff --git a/uiWidgets/SystemInfoBox.go b/uiWidgets/SystemInfoBox.go index 4a71991c..3445370d 100755 --- a/uiWidgets/SystemInfoBox.go +++ b/uiWidgets/SystemInfoBox.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go index 05e346a1..63b12762 100755 --- a/uiWidgets/TemperatureIncreaseButton.go +++ b/uiWidgets/TemperatureIncreaseButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) diff --git a/uiWidgets/TemperaturePresetButton.go b/uiWidgets/TemperaturePresetButton.go index 26ffbd47..651f32fd 100755 --- a/uiWidgets/TemperaturePresetButton.go +++ b/uiWidgets/TemperaturePresetButton.go @@ -3,6 +3,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -12,7 +13,7 @@ type TemperaturePresetButton struct { client *octoprintApis.Client selectToolStepButton *SelectToolStepButton imageFileName string - temperaturePreset *octoprintApis.TemperaturePreset + temperaturePreset *dataModels.TemperaturePreset callback func() } @@ -20,7 +21,7 @@ func CreateTemperaturePresetButton( client *octoprintApis.Client, selectToolStepButton *SelectToolStepButton, imageFileName string, - temperaturePreset *octoprintApis.TemperaturePreset, + temperaturePreset *dataModels.TemperaturePreset, callback func(), ) *TemperaturePresetButton { presetName := utils.StrEllipsisLen(temperaturePreset.Name, 10) diff --git a/uiWidgets/TemperatureStatusBox.go b/uiWidgets/TemperatureStatusBox.go index b655ec8e..15ed01d8 100755 --- a/uiWidgets/TemperatureStatusBox.go +++ b/uiWidgets/TemperatureStatusBox.go @@ -6,6 +6,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -44,7 +45,7 @@ func CreateTemperatureStatusBox( instance.SetVAlign(gtk.ALIGN_CENTER) instance.SetHAlign(gtk.ALIGN_CENTER) - var bedTemperatureData *octoprintApis.TemperatureData = nil + var bedTemperatureData *dataModels.TemperatureData = nil var hotendIndex int = 0 var hotendCount int = utils.GetToolheadCount(client) for key, temperatureData := range currentTemperatureData { @@ -80,7 +81,7 @@ func CreateTemperatureStatusBox( } // interfaces.ITemperatureDataDisplay -func (this *TemperatureStatusBox) UpdateTemperatureData(currentTemperatureData map[string]octoprintApis.TemperatureData) { +func (this *TemperatureStatusBox) UpdateTemperatureData(currentTemperatureData map[string]dataModels.TemperatureData) { for key, temperatureData := range currentTemperatureData { if labelWithImage, ok := this.labelWithImages[key]; ok { temperatureDataString := utils.GetTemperatureDataString(temperatureData) diff --git a/uiWidgets/ToolButton.go b/uiWidgets/ToolButton.go index 2320e6e2..6b5f58ff 100755 --- a/uiWidgets/ToolButton.go +++ b/uiWidgets/ToolButton.go @@ -6,11 +6,11 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" ) - func ToolImageFileName( index int, ) string { @@ -78,7 +78,7 @@ func (this *ToolButton) UpdateStatus(heating bool) { this.isHeating = heating } -func (this *ToolButton) SetTemperatures(temperatureData octoprintApis.TemperatureData) { +func (this *ToolButton) SetTemperatures(temperatureData dataModels.TemperatureData) { text := utils.GetTemperatureDataString(temperatureData) this.SetLabel(text) this.UpdateStatus(temperatureData.Target > 0) diff --git a/utils/background_task.go b/utils/BackgroundTask.go similarity index 99% rename from utils/background_task.go rename to utils/BackgroundTask.go index a01d444f..51f66838 100755 --- a/utils/background_task.go +++ b/utils/BackgroundTask.go @@ -7,6 +7,7 @@ import ( "github.com/gotk3/gotk3/glib" ) + type BackgroundTask struct { sync.Mutex diff --git a/utils/FileResponsesSortedByDate.go b/utils/FileResponsesSortedByDate.go index 0ded5105..dae8fb77 100755 --- a/utils/FileResponsesSortedByDate.go +++ b/utils/FileResponsesSortedByDate.go @@ -4,10 +4,13 @@ import ( // "fmt" // "sort" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) -type FileResponsesSortedByDate []*octoprintApis.FileResponse + +type FileResponsesSortedByDate []*dataModels.FileResponse func (this FileResponsesSortedByDate) Len() int { return len(this) diff --git a/utils/FileResponsesSortedByName.go b/utils/FileResponsesSortedByName.go index f9ceca5f..b05dd5ef 100755 --- a/utils/FileResponsesSortedByName.go +++ b/utils/FileResponsesSortedByName.go @@ -5,10 +5,13 @@ import ( // "sort" // "strings" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) -type FileResponsesSortedByName []*octoprintApis.FileResponse + +type FileResponsesSortedByName []*dataModels.FileResponse func (this FileResponsesSortedByName) Len() int { return len(this) diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go index 89ec0520..f4836c77 100755 --- a/utils/LocationHistory.go +++ b/utils/LocationHistory.go @@ -4,18 +4,20 @@ import ( // "fmt" // "sort" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + // "github.com/Z-Bolt/OctoScreen/uiWidgets" ) type LocationHistory struct { - Locations []octoprintApis.Location + Locations []dataModels.Location } func (this *LocationHistory) Length() int { return len(this.Locations) } -func (this *LocationHistory) CurrentLocation() octoprintApis.Location { +func (this *LocationHistory) CurrentLocation() dataModels.Location { length := this.Length() if length < 1 { panic("LocationHistory.current() - locations is empty") @@ -26,7 +28,7 @@ func (this *LocationHistory) CurrentLocation() octoprintApis.Location { func (this *LocationHistory) GoForward(folder string) { newLocation := string(this.CurrentLocation()) + "/" + folder - this.Locations = append(this.Locations, octoprintApis.Location(newLocation)) + this.Locations = append(this.Locations, dataModels.Location(newLocation)) } func (this *LocationHistory) GoBack() { diff --git a/utils/UpdateTemperaturesBackgroundTask.go b/utils/UpdateTemperaturesBackgroundTask.go index 02e203ab..4915ced5 100755 --- a/utils/UpdateTemperaturesBackgroundTask.go +++ b/utils/UpdateTemperaturesBackgroundTask.go @@ -5,9 +5,11 @@ import ( "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) -// TODO: convert this into a singleton class + +// TODO: convert this into a singleton var UpdateTemperaturesBackgroundTask *BackgroundTask = nil var temperatureDataDisplays []interfaces.ITemperatureDataDisplay diff --git a/utils/environment.go b/utils/environment.go index bae21531..9e87a1a5 100755 --- a/utils/environment.go +++ b/utils/environment.go @@ -83,7 +83,19 @@ func DumpEnvironmentVariables() { // Required environment variables Logger.Infof("Required environment variables:") dumpEnvironmentVariable(EnvBaseURL) + + // TODO: revisit this! + // 1. remove OCTOPRINT_APIKEY from option settings + // 2. make the octoprint config path required + // 3. update code... use only one path to get the api key octoprint) + // 4. update code... make octoprint config path required + // 5. update code... read api key from octoprint config + // 6. dump api key (obfuscated though) + // 7. update docs + // 8. make sure what's dumped to the log is correct, for both when present and when missing. dumpObfuscatedEnvironmentVariable(EnvAPIKey) + + dumpEnvironmentVariable(EnvStylePath) // Optional environment variables diff --git a/utils/filament.go b/utils/filament.go new file mode 100755 index 00000000..8f802a8d --- /dev/null +++ b/utils/filament.go @@ -0,0 +1,71 @@ +package utils + +import ( + // "errors" + + "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" +) + + +func Extrude( + client *octoprintApis.Client, + isForward bool, + extruderId string, + parentWindow *gtk.Window, + flowRatePercentage int, + length int, +) { + var action string + if isForward { + action = "extrude" + } else { + action = "retract" + } + + if CheckIfHotendTemperatureIsTooLow(client, extruderId, action, parentWindow) { + Logger.Error("filament.Extrude() - temperature is too low") + // No need to display an error - CheckIfHotendTemperatureIsTooLow() displays an error to the user + // if the temperature is too low. + return + } + + Logger.Infof("filament.Extrude() - setting flow rate percentage of %d", flowRatePercentage) + if err := SetFlowRate(client, flowRatePercentage); err != nil { + LogError("filament.Extrude()", "SetFlowRate()", err) + // TODO: display error? + return + } + + cmd := &octoprintApis.ToolExtrudeRequest{} + if isForward { + cmd.Amount = length + } else { + cmd.Amount = -length + } + + Logger.Infof("filament.Extrude() - sending extrude request with length of: %d", cmd.Amount) + if err := cmd.Do(client); err != nil { + LogError("filament.Extrude()", "Do(ToolExtrudeRequest)", err) + // TODO: display error? + return + } +} + + +func SetFlowRate( + client *octoprintApis.Client, + flowRatePercentage int, +) error { + cmd := &octoprintApis.ToolFlowRateRequest{} + cmd.Factor = flowRatePercentage + + Logger.Infof("filament.SetFlowRate() - changing flow rate to %d%%", cmd.Factor) + if err := cmd.Do(client); err != nil { + LogError("filament.SetFlowRate()", "Go(ToolFlowRateRequest)", err) + return err + } + + return nil +} diff --git a/utils/file_utils.go b/utils/file_utils.go index 94ef6d66..d0150952 100755 --- a/utils/file_utils.go +++ b/utils/file_utils.go @@ -2,15 +2,34 @@ package utils import ( "os" + // "strings" ) // FileExists checks if a file exists and is not a directory. // From https://golangcode.com/check-if-a-file-exists/ func FileExists(filename string) bool { - info, err := os.Stat(filename) - if os.IsNotExist(err) { + info := exists(filename) + if info == nil { return false } return !info.IsDir() } + +func FolderExists(filename string) bool { + info := exists(filename) + if info == nil { + return false + } + + return info.IsDir() +} + +func exists(filename string) os.FileInfo { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + return nil + } + + return info +} diff --git a/utils/tools.go b/utils/tools.go index f702c6a3..ed547c71 100755 --- a/utils/tools.go +++ b/utils/tools.go @@ -2,11 +2,12 @@ package utils import ( "fmt" - "strings" "strconv" + "strings" "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) var cachedToolheadCount = -1 @@ -18,18 +19,18 @@ func GetToolheadCount(client *octoprintApis.Client) int { connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(client) if err != nil { - LogError("toolhaad.GetToolheadCount()", "Do(ConnectionRequest)", err) + LogError("Tools.GetToolheadCount()", "version.Get()", err) return 0 } printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(client) if err != nil { - LogError("toolhaad.GetToolheadCount()", "Do(PrinterProfilesRequest)", err) + LogError("Tools.GetToolheadCount()", "Do(PrinterProfilesRequest)", err) return 0 } cachedToolheadCount = printerProfile.Extruder.Count - if printerProfile.Extruder.SharedNozzle { + if printerProfile.Extruder.HasSharedNozzle { cachedToolheadCount = 1 } else if cachedToolheadCount > 4 { cachedToolheadCount = 4 @@ -49,18 +50,18 @@ func GetToolheadCount(client *octoprintApis.Client) int { func GetDisplayNameForTool(toolName string) string { // Since this is such a hack, lets add some bounds checking if toolName == "" { - Logger.Error("toolhaad.GetDisplayNameForTool() - toolName is empty") + Logger.Error("Tools..GetDisplayNameForTool() - toolName is empty") return "" } lowerCaseName := strings.ToLower(toolName) if strings.LastIndex(lowerCaseName, "tool") != 0 { - Logger.Errorf("toolhaad.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) + Logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) return "" } if len(toolName) != 5 { - Logger.Errorf("toolhaad.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) + Logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) return "" } @@ -76,7 +77,7 @@ func GetToolTarget(client *octoprintApis.Client, tool string) (float64, error) { Logger.Debug("entering Tools.GetToolTarget()") - fullStateRequest, err := (&octoprintApis.FullStateRequest{ + fullStateRespone, err := (&octoprintApis.FullStateRequest{ Exclude: []string{"sd", "state"}, }).Do(client) @@ -87,7 +88,7 @@ func GetToolTarget(client *octoprintApis.Client, tool string) (float64, error) { return -1, err } - currentTemperatureData, ok := fullStateRequest.Temperature.CurrentTemperatureData[tool] + currentTemperatureData, ok := fullStateRespone.Temperature.CurrentTemperatureData[tool] if !ok { Logger.Debug("leaving Tools.GetToolTarget()") return -1, fmt.Errorf("unable to find tool %q", tool) @@ -115,7 +116,7 @@ func SetToolTarget(client *octoprintApis.Client, tool string, target float64) er } -func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]octoprintApis.TemperatureData, error) { +func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]dataModels.TemperatureData, error) { Logger.Debug("entering Tools.GetCurrentTemperatureData()") temperatureDataResponse, err := (&octoprintApis.TemperatureDataRequest{}).Do(client) @@ -147,7 +148,7 @@ func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]octopri } -func CurrentHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, action string, parentWindow *gtk.Window) bool { +func CheckIfHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, action string, parentWindow *gtk.Window) bool { currentTemperatureData, err := GetCurrentTemperatureData(client) if err != nil { LogError("tools.CurrentHotendTemperatureIsTooLow()", "GetCurrentTemperatureData()", err) @@ -156,15 +157,21 @@ func CurrentHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, temperatureData := currentTemperatureData[extruderId] + // If the temperature of the hotend is too low, display an error. if HotendTemperatureIsTooLow(temperatureData, action, parentWindow) { - LogError("tools.CurrentHotendTemperatureIsTooLow()", "HotendTemperatureIsTooLow()", err) + errorMessage := fmt.Sprintf( + "The temperature of the hotend is too low to %s.\n(the current temperature is only %.0f°C)\n\nPlease increase the temperature and try again.", + action, + temperatureData.Actual, + ) + ErrorMessageDialogBox(parentWindow, errorMessage) + return true } return false } - func GetToolheadFileName(hotendIndex, hotendCount int) string { strImageFileName := "" if hotendIndex == 1 && hotendCount == 1 { @@ -198,6 +205,29 @@ func GetNozzleFileName(hotendIndex, hotendCount int) string { return strImageFileName } -func GetTemperatureDataString(temperatureData octoprintApis.TemperatureData) string { +func GetTemperatureDataString(temperatureData dataModels.TemperatureData) string { return fmt.Sprintf("%.0f°C / %.0f°C", temperatureData.Actual, temperatureData.Target) -} \ No newline at end of file +} + + +// TODO: maybe move HotendTemperatureIsTooLow into a hotend utils file? + +const MIN_HOTEND_TEMPERATURE = 150.0 + +func HotendTemperatureIsTooLow( + temperatureData dataModels.TemperatureData, + action string, + parentWindow *gtk.Window, +) bool { + targetTemperature := temperatureData.Target + Logger.Infof("tools.HotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) + + actualTemperature := temperatureData.Actual + Logger.Infof("tools.HotendTemperatureIsTooLow() - actualTemperature is %.2f", actualTemperature) + + if targetTemperature <= MIN_HOTEND_TEMPERATURE || actualTemperature <= MIN_HOTEND_TEMPERATURE { + return true + } + + return false +} diff --git a/utils/ui_utils.go b/utils/ui_utils.go index 1c13736b..4c960587 100755 --- a/utils/ui_utils.go +++ b/utils/ui_utils.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" - "github.com/Z-Bolt/OctoScreen/octoprintApis" ) @@ -135,7 +134,7 @@ func messageDialogBox(parentWindow *gtk.Window, messageType gtk.MessageType, mes box, _ := dialogBox.GetContentArea() box.SetMarginStart(25) box.SetMarginEnd(25) - box.SetMarginTop(50) + box.SetMarginTop(20) box.SetMarginBottom(10) ctx, _ := dialogBox.GetStyleContext() @@ -144,22 +143,20 @@ func messageDialogBox(parentWindow *gtk.Window, messageType gtk.MessageType, mes dialogBox.Run() } -func HotendTemperatureIsTooLow(temperatureData octoprintApis.TemperatureData, action string, parentWindow *gtk.Window) bool { - targetTemperature := temperatureData.Target - Logger.Infof("filament.hotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) - actualTemperature := temperatureData.Actual - Logger.Infof("filament.hotendTemperatureIsTooLow() - actualTemperature is %.2f", actualTemperature) +// func hotendTemperatureIsTooLow(temperatureData octoprint.TemperatureData, action string, parentWindow *gtk.Window) bool { +// targetTemperature := temperatureData.Target +// Logger.Infof("ui_utils.HotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) - // If the temperature of the hotend is too low, display an error. - if targetTemperature <= 150.0 || actualTemperature <= 150.0 { - errorMessage := fmt.Sprintf("The temperature of the hotend is too low to %s.\n(the current temperature is only %.0f°C)\n\nPlease increase the temperature and try again.", action, actualTemperature) - ErrorMessageDialogBox(parentWindow, errorMessage) - return true - } +// actualTemperature := temperatureData.Actual +// Logger.Infof("ui_utils.HotendTemperatureIsTooLow() - actualTemperature is %.2f", actualTemperature) - return false -} +// if targetTemperature <= 150.0 || actualTemperature <= 150.0 { +// return true +// } + +// return false +// } func EmptyTheContainer(container *gtk.Container) { From c2ae816fb22b4e6bb913cf34c277ff78450de5c7 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 1 Feb 2021 20:53:40 -0800 Subject: [PATCH 29/94] Hard fork of mcuadros/go-octoprint-updated code to use new octoprintApis package and new dataModels package --- ui/FilamentPanel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/FilamentPanel.go b/ui/FilamentPanel.go index 66092bc3..9b5a2e38 100755 --- a/ui/FilamentPanel.go +++ b/ui/FilamentPanel.go @@ -89,7 +89,7 @@ func (this *filamentPanel) initialize() { this.flowRateStepButton, this.selectToolStepButton, true, - int(this.UI.Settings.FilamentInLength), // jab revisit + int(this.UI.Settings.FilamentInLength), ) this.Grid().Attach(this.filamentLoadButton, 0, 1, 1, 1) @@ -102,7 +102,7 @@ func (this *filamentPanel) initialize() { this.flowRateStepButton, this.selectToolStepButton, false, - int(this.UI.Settings.FilamentOutLength), // jab revisit + int(this.UI.Settings.FilamentOutLength), ) this.Grid().Attach(this.filamentUnloadButton, 3, 1, 1, 1) From 9f08883ed31f8a0f1bb2f89b45acf1097eb62b38 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Feb 2021 20:02:18 -0800 Subject: [PATCH 30/94] changed black background to transparent --- styles/z-bolt/images/open.svg | 24 +++-- styles/z-bolt/images/z-calibration.svg | 120 ++++----------------- styles/z-bolt/images/z-offset-decrease.svg | 4 +- styles/z-bolt/images/z-offset-increase.svg | 4 +- 4 files changed, 40 insertions(+), 112 deletions(-) diff --git a/styles/z-bolt/images/open.svg b/styles/z-bolt/images/open.svg index 7802389f..b8fb6fd9 100644 --- a/styles/z-bolt/images/open.svg +++ b/styles/z-bolt/images/open.svg @@ -1,11 +1,13 @@ - - - - open - Created with Sketch. - - - - - - \ No newline at end of file + + + + + + + + + + + diff --git a/styles/z-bolt/images/z-calibration.svg b/styles/z-bolt/images/z-calibration.svg index a30ef8d4..a2e7642d 100644 --- a/styles/z-bolt/images/z-calibration.svg +++ b/styles/z-bolt/images/z-calibration.svg @@ -1,97 +1,23 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/styles/z-bolt/images/z-offset-decrease.svg b/styles/z-bolt/images/z-offset-decrease.svg index 6ec00dd5..c0bd6dbe 100644 --- a/styles/z-bolt/images/z-offset-decrease.svg +++ b/styles/z-bolt/images/z-offset-decrease.svg @@ -47,6 +47,6 @@ - + diff --git a/styles/z-bolt/images/z-offset-increase.svg b/styles/z-bolt/images/z-offset-increase.svg index f0a836df..4a99b1f0 100644 --- a/styles/z-bolt/images/z-offset-increase.svg +++ b/styles/z-bolt/images/z-offset-increase.svg @@ -12,7 +12,7 @@ @@ -47,6 +47,6 @@ - From f1b31d57a04eec1d99c986627df1edec70b292d6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Feb 2021 10:49:08 -0800 Subject: [PATCH 31/94] added new extruder variation --- docs/ButtonImages.html | 18 ++++++++++++ styles/z-bolt/images/extruder-typeB-1.svg | 35 ++++++++++++++++++++++ styles/z-bolt/images/extruder-typeB-2.svg | 35 ++++++++++++++++++++++ styles/z-bolt/images/extruder-typeB-3.svg | 35 ++++++++++++++++++++++ styles/z-bolt/images/extruder-typeB-4.svg | 35 ++++++++++++++++++++++ styles/z-bolt/images/extruder-typeB.svg | 36 +++++++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100755 styles/z-bolt/images/extruder-typeB-1.svg create mode 100755 styles/z-bolt/images/extruder-typeB-2.svg create mode 100755 styles/z-bolt/images/extruder-typeB-3.svg create mode 100755 styles/z-bolt/images/extruder-typeB-4.svg create mode 100755 styles/z-bolt/images/extruder-typeB.svg diff --git a/docs/ButtonImages.html b/docs/ButtonImages.html index 61ffbfdc..789e8a89 100755 --- a/docs/ButtonImages.html +++ b/docs/ButtonImages.html @@ -4,6 +4,7 @@ body { font-family: Arial, Helvetica, sans-serif; color: white; + background-color: rgb(143, 194, 60); background-color: black; margin: 20px; } @@ -65,6 +66,23 @@
extruder
+ + +
extruder-typeB
+ + +
extruder-typeB-1
+ + +
extruder-typeB-2
+ + +
extruder-typeB-3
+ + +
extruder-typeB-4
+ +
fan-off
diff --git a/styles/z-bolt/images/extruder-typeB-1.svg b/styles/z-bolt/images/extruder-typeB-1.svg new file mode 100755 index 00000000..abff3744 --- /dev/null +++ b/styles/z-bolt/images/extruder-typeB-1.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + 1 + + + diff --git a/styles/z-bolt/images/extruder-typeB-2.svg b/styles/z-bolt/images/extruder-typeB-2.svg new file mode 100755 index 00000000..b99cb617 --- /dev/null +++ b/styles/z-bolt/images/extruder-typeB-2.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + 2 + + + diff --git a/styles/z-bolt/images/extruder-typeB-3.svg b/styles/z-bolt/images/extruder-typeB-3.svg new file mode 100755 index 00000000..b27be67a --- /dev/null +++ b/styles/z-bolt/images/extruder-typeB-3.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + 3 + + + diff --git a/styles/z-bolt/images/extruder-typeB-4.svg b/styles/z-bolt/images/extruder-typeB-4.svg new file mode 100755 index 00000000..49856ebc --- /dev/null +++ b/styles/z-bolt/images/extruder-typeB-4.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + 4 + + + diff --git a/styles/z-bolt/images/extruder-typeB.svg b/styles/z-bolt/images/extruder-typeB.svg new file mode 100755 index 00000000..87cc1d5e --- /dev/null +++ b/styles/z-bolt/images/extruder-typeB.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + 1 + + + From 3123c0a4e3f76a48401641fa1bcfcd1df3ebfab2 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Feb 2021 15:23:09 -0800 Subject: [PATCH 32/94] made entire row in Files list to a button, making it easier to select --- styles/z-bolt/style.css | 42 +++++-- ui/FilesPanel.go | 251 +++++++++++++++++++++++++--------------- 2 files changed, 188 insertions(+), 105 deletions(-) diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css index 0cd0bb10..a4143852 100755 --- a/styles/z-bolt/style.css +++ b/styles/z-bolt/style.css @@ -50,6 +50,20 @@ progress { } +.list-box-row { + margin: 0; + border: 0; + padding: 0; +} + +.list-item-button { + margin: 0; + border: 0; + padding: 0 0 0 6px; +} + + + /* Button styles *********************************************************** */ button { @@ -71,23 +85,23 @@ button.color-none { border-bottom: 8px solid black; } -button.color1 { +.color1 { border-bottom: 8px solid #ED6500; } -button.color2 { +.color2 { border-bottom: 8px solid #B10080; } -button.color3 { +.color3 { border-bottom: 8px solid #009384; } -button.color4 { +.color4 { border-bottom: 8px solid #A7E100; } -button.color-dash-1 { +.color-dash-1 { background-image: linear-gradient(to right, #560FD1 60%, rgba(255, 255, 255, 0) 20%); background-position: bottom; @@ -95,7 +109,7 @@ button.color-dash-1 { background-repeat: repeat-x; } -button.color-dash-2 { +.color-dash-2 { background-image: linear-gradient(to right, #C8ADF8 60%, rgba(255, 255, 255, 0) 20%); background-position: bottom; @@ -103,11 +117,11 @@ button.color-dash-2 { background-repeat: repeat-x; } -button.color-warning-sign-yellow { +.color-warning-sign-yellow { border-bottom: 8px solid #FFE700; } -button.color-warning-sign-yellow-dark { +.color-warning-sign-yellow-dark { border-bottom: 8px solid #E6D300; } @@ -118,9 +132,6 @@ button.active { background-color: #20303D; } -button.file-list { - margin: 0px; -} entry { @@ -349,6 +360,15 @@ Do not use any of these in production. background-color: orange; } +.purple-background { + background-color: purple; +} + +.cyan-background { + background-color: cyan; +} + + .red-foreground { color: red } diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 05b3289f..22b88ec2 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -54,13 +54,13 @@ func (this *filesPanel) initialize() { box := utils.MustBox(gtk.ORIENTATION_VERTICAL, 0) box.Add(scroll) - box.Add(this.createActionBar()) + box.Add(this.createActionFooter()) this.Grid().Add(box) this.doLoadFiles() } -func (this *filesPanel) createActionBar() gtk.IWidget { +func (this *filesPanel) createActionFooter() gtk.IWidget { actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) actionBar.SetHAlign(gtk.ALIGN_END) actionBar.SetHExpand(true) @@ -146,13 +146,14 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { func (this *filesPanel) addRootLocations() { this.addMessage("Select source location:") - this.addRootLocation(dataModels.Local, 0) - this.addRootLocation(dataModels.SDCard, 1) + this.addRootLocation(dataModels.Local) + this.addRootLocation(dataModels.SDCard) } func (this *filesPanel) addMessage(message string) { nameLabel := this.createNameLabel(message) labelsBox := this.createLabelsBox(nameLabel, nil) + labelsBox.SetMarginStart(10) topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) topBox.Add(labelsBox) @@ -166,7 +167,16 @@ func (this *filesPanel) addMessage(message string) { this.listBox.Add(listItemFrame) } -func (this *filesPanel) addRootLocation(location dataModels.Location, index int) { +func (this *filesPanel) addRootLocation(location dataModels.Location) { + rootLocationButton := this.createRootLocationButton(location) + + listBoxRow, _ := gtk.ListBoxRowNew() + listBoxRow.Add(rootLocationButton) + + this.listBox.Add(listBoxRow) +} + +func (this *filesPanel) createRootLocationButton(location dataModels.Location) *gtk.Button { var itemImage *gtk.Image if location == dataModels.Local { itemImage = utils.MustImageFromFileWithSize("octoprint-tentacle.svg", this.Scaled(35), this.Scaled(35)) @@ -193,24 +203,29 @@ func (this *filesPanel) addRootLocation(location dataModels.Location, index int) topBox.Add(labelsBox) - var itemButton *gtk.Button + var actionImage *gtk.Image if location == dataModels.Local { - itemButton = this.createOpenLocationButton(location) + actionImage = this.createOpenLocationImage(0) } else { - itemButton = this.createOpenLocationButton(location) + actionImage = this.createOpenLocationImage(1) } actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - actionBox.Add(itemButton) + actionBox.Add(actionImage) topBox.Add(actionBox) - listItemBox := this.createListItemBox() - listItemBox.Add(topBox) + rootLocationButton, _ := gtk.ButtonNew() + rootLocationButton.Connect("clicked", func() { + this.locationHistory = utils.LocationHistory { + Locations: []dataModels.Location{location}, + } - listItemFrame, _ := gtk.FrameNew("") - listItemFrame.Add(listItemBox) + this.doLoadFiles() + }) - this.listBox.Add(listItemFrame) + rootLocationButton.Add(topBox) + + return rootLocationButton } func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) { @@ -231,20 +246,65 @@ func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) { } } +func (this *filesPanel) addItem( + fileResponse *dataModels.FileResponse, + index int, +) { + /* + Object hierarchy: + + listBox + listBoxRow + listItemButton (to handle to click for the entire item amd all of the child controls) + listItemBox (to layout the objects, in this case the two rows within the button) + infoAndActionRow (a Box) + previewRow (a Box) + */ + + + listItemBox := this.createListItemBox() -func (this *filesPanel) addItem(fileResponse *dataModels.FileResponse, index int) { isFolder := fileResponse.IsFolder() + infoAndActionRow := this.createInfoAndActionRow(fileResponse, index, isFolder) + listItemBox.Add(infoAndActionRow) + if !isFolder { + previewRow := this.createPreviewRow(fileResponse) + listItemBox.Add(previewRow) + } + listItemButton := this.createListItemButton(fileResponse, index, isFolder) + listItemButton.Add(listItemBox) + + listBoxRow, _ := gtk.ListBoxRowNew() + listBoxRowStyleContext, _ := listBoxRow.GetStyleContext() + listBoxRowStyleContext.AddClass("list-box-row") + if index % 2 != 0 { + listBoxRowStyleContext.AddClass("list-item-nth-child-even") + } + listBoxRow.Add(listItemButton) + + this.listBox.Add(listBoxRow) +} + +func (this *filesPanel) createInfoAndActionRow( + fileResponse *dataModels.FileResponse, + index int, + isFolder bool, +) *gtk.Box { + infoAndActionRow := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) + + + // Column 1: Folder or File icon var itemImage *gtk.Image if isFolder { itemImage = utils.MustImageFromFileWithSize("folder.svg", this.Scaled(35), this.Scaled(35)) } else { itemImage = utils.MustImageFromFileWithSize("file-gcode.svg", this.Scaled(35), this.Scaled(35)) } + infoAndActionRow.Add(itemImage) - topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - topBox.Add(itemImage) + // Column 2: File name and file info name := fileResponse.Name nameLabel := this.createNameLabel(name) @@ -261,42 +321,74 @@ func (this *filesPanel) addItem(fileResponse *dataModels.FileResponse, index int } labelsBox := this.createLabelsBox(nameLabel, infoLabel) - topBox.Add(labelsBox) + infoAndActionRow.Add(labelsBox) - var itemButton *gtk.Button + + // Column 3: printer image + var actionImage *gtk.Image if isFolder { - itemButton = this.createOpenFolderButton(fileResponse) + actionImage = this.createOpenLocationImage(index) } else { - itemButton = this.createLoadAndPrintButton("print.svg", fileResponse) + actionImage = this.createPrintImage() } actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) - actionBox.Add(itemButton) - topBox.Add(actionBox) + actionBox.Add(actionImage) - listItemBox := this.createListItemBox() - listItemBox.Add(topBox) + infoAndActionRow.Add(actionBox) - if !isFolder { - this.addThumbnail(fileResponse, listItemBox) - } + return infoAndActionRow +} - listItemFrame, _ := gtk.FrameNew("") - listItemFrame.Add(listItemBox) +func (this *filesPanel) createPreviewRow(fileResponse *dataModels.FileResponse) *gtk.Box { + previewRow := this.createListItemBox() + this.addThumbnail(fileResponse, previewRow) + + return previewRow +} - itemButtonStyleContext, _ := itemButton.GetStyleContext() - listItemBoxStyleContext, _:= listItemBox.GetStyleContext() - listItemFrameStyleContext, _ := listItemFrame.GetStyleContext() +func (this *filesPanel) createListItemButton( + fileResponse *dataModels.FileResponse, + index int, + isFolder bool, +) *gtk.Button { + listItemButton, _ := gtk.ButtonNew() + listItemButtonStyleContext, _ := listItemButton.GetStyleContext() + listItemButtonStyleContext.AddClass("list-item-button") if index % 2 != 0 { - itemButtonStyleContext.AddClass("list-item-nth-child-even") - listItemBoxStyleContext.AddClass("list-item-nth-child-even") - listItemFrameStyleContext.AddClass("list-item-nth-child-even") + listItemButtonStyleContext.AddClass("list-item-nth-child-even") } - this.listBox.Add(listItemFrame) + if isFolder { + listItemButton.Connect("clicked", func() { + this.locationHistory.GoForward(fileResponse.Name) + this.doLoadFiles() + }) + } else { + listItemButton.Connect("clicked", utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { + selectFileRequest := &octoprintApis.SelectFileRequest{} + + // Set the location to "local" or "sdcard" + selectFileRequest.Location = this.locationHistory.Locations[0] + + selectFileRequest.Path = fileResponse.Path + selectFileRequest.Print = true + + utils.Logger.Infof("Loading file %q", fileResponse.Name) + if err := selectFileRequest.Do(this.UI.Client); err != nil { + utils.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) + return + } + })) + } + + return listItemButton } -func (this *filesPanel) createLabelsBox(nameLabel, infoLabel *gtk.Label) *gtk.Box { +func (this *filesPanel) createLabelsBox( + nameLabel *gtk.Label, + infoLabel *gtk.Label, +) *gtk.Box { labelsBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) if nameLabel != nil { labelsBox.Add(nameLabel) @@ -323,17 +415,19 @@ func (this *filesPanel) createNameLabel(name string) *gtk.Label { } func (this *filesPanel) createListItemBox() *gtk.Box { - listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5) - listItemBox.SetMarginTop(1) - listItemBox.SetMarginBottom(1) - listItemBox.SetMarginStart(15) - listItemBox.SetMarginEnd(15) - listItemBox.SetHExpand(true) + listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 0) + listItemBox.SetMarginTop(0) + listItemBox.SetMarginBottom(0) + listItemBox.SetMarginStart(0) + listItemBox.SetMarginEnd(0) return listItemBox } -func (this *filesPanel) addThumbnail(fileResponse *dataModels.FileResponse, listItemBox *gtk.Box) { +func (this *filesPanel) addThumbnail( + fileResponse *dataModels.FileResponse, + listItemBox *gtk.Box, +) { if fileResponse.Thumbnail != "" { utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) @@ -365,65 +459,34 @@ func (this *filesPanel) addThumbnail(fileResponse *dataModels.FileResponse, list } } +func (this *filesPanel) createOpenLocationImage(index int) *gtk.Image { + colorClass := fmt.Sprintf("color%d", (index % 4) + 1) -func (this *filesPanel) createOpenLocationButton(location dataModels.Location) *gtk.Button { - image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) - button := utils.MustButton(image, func() { - this.locationHistory = utils.LocationHistory { - Locations: []dataModels.Location{location}, - } - - this.doLoadFiles() - }) - - ctx, _ := button.GetStyleContext() - ctx.AddClass("color1") - ctx.AddClass("file-list") - - return button + return this.createActionImage("open.svg", colorClass) } -func (this *filesPanel) createOpenFolderButton(fileResponse *dataModels.FileResponse) *gtk.Button { - image := utils.MustImageFromFileWithSize("open.svg", this.Scaled(40), this.Scaled(40)) - button := utils.MustButton(image, func() { - this.locationHistory.GoForward(fileResponse.Name) - this.doLoadFiles() - }) - - ctx, _ := button.GetStyleContext() - ctx.AddClass("color1") - ctx.AddClass("file-list") - - return button +func (this *filesPanel) createPrintImage() *gtk.Image { + return this.createActionImage("print.svg", "color-warning-sign-yellow") } -func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileResponse *dataModels.FileResponse) *gtk.Button { - button := utils.MustButton( - utils.MustImageFromFileWithSize(imageFileName, this.Scaled(40), this.Scaled(40)), - utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { - selectFileRequest := &octoprintApis.SelectFileRequest{} - - // Set the location to "local" or "sdcard" - selectFileRequest.Location = this.locationHistory.Locations[0] - - selectFileRequest.Path = fileResponse.Path - selectFileRequest.Print = true - - utils.Logger.Infof("Loading file %q", fileResponse.Name) - if err := selectFileRequest.Do(this.UI.Client); err != nil { - utils.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) - return - } - }), +func (this *filesPanel) createActionImage( + imageFileName string, + colorClass string, +) *gtk.Image { + image := utils.MustImageFromFileWithSize( + imageFileName, + this.Scaled(40), + this.Scaled(40), ) - ctx, _ := button.GetStyleContext() - ctx.AddClass("color-warning-sign-yellow") - ctx.AddClass("file-list") + imageStyleContext, _ := image.GetStyleContext() + imageStyleContext.AddClass(colorClass) - return button + return image } + + /* func (this *filesPanel) isReady() bool { state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client) From 780c9de5ef2a1bd9005011f9bd7245f1c303ab27 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Feb 2021 17:20:11 -0800 Subject: [PATCH 33/94] chaged border of dialog to make it more noticable --- styles/z-bolt/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css index a4143852..3721399e 100755 --- a/styles/z-bolt/style.css +++ b/styles/z-bolt/style.css @@ -150,7 +150,7 @@ button.keyboard { } .dialog { - border: 2px solid black; + border: 4px solid white; font-size: 20px; padding: 50px; background-color: #333; From 5ddebeff56ff405be8eff9d1c1f12478346e9c5e Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Feb 2021 17:22:54 -0800 Subject: [PATCH 34/94] added file name to print confirmation dialog box --- ui/FilesPanel.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 22b88ec2..f2f490aa 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -365,7 +365,16 @@ func (this *filesPanel) createListItemButton( this.doLoadFiles() }) } else { - listItemButton.Connect("clicked", utils.MustConfirmDialogBox(this.UI.window, "Do you wish to proceed?", func() { + message := "" + strLen := len(fileResponse.Name) + if strLen <= 20 { + message = fmt.Sprintf("Do you wish to print %s?", fileResponse.Name) + } else { + truncatedFileName := utils.TruncateString(fileResponse.Name, 40) + message = fmt.Sprintf("Do you wish to print\n%s?", truncatedFileName) + } + + listItemButton.Connect("clicked", utils.MustConfirmDialogBox(this.UI.window, message, func() { selectFileRequest := &octoprintApis.SelectFileRequest{} // Set the location to "local" or "sdcard" From 5f0ae24dc385ed3f754a0b969a4d339295a318ce Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Feb 2021 17:24:14 -0800 Subject: [PATCH 35/94] added some additional bounds checking to TruncateString() --- utils/string_utils.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/utils/string_utils.go b/utils/string_utils.go index a673511e..668f92bc 100755 --- a/utils/string_utils.go +++ b/utils/string_utils.go @@ -1,4 +1,3 @@ - package utils import ( @@ -55,19 +54,22 @@ func StrEllipsisLen(name string, length int) string { return name } -func TruncateString(str string, length int) string { - if length < 3 { - length = 3 +func TruncateString(str string, maxLength int) string { + if maxLength < 3 { + maxLength = 3 } - truncateString := str - if len(str) > length { - if length > 3 { - length -= 3 - } + strLen := len(str) + if strLen <= maxLength { + return str + } - truncateString = str[0:length] + "..." + truncateString := str + if maxLength > 3 { + maxLength -= 3 } + truncateString = str[0:maxLength] + "..." + return truncateString } From 7c3bebdab23632a1ccca33034c343ec7b8f6f0f6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 15 Feb 2021 19:16:36 -0800 Subject: [PATCH 36/94] made small design modification to the extruder-typeB images --- styles/z-bolt/images/extruder-typeB-1.svg | 45 +++++++++++++---------- styles/z-bolt/images/extruder-typeB-2.svg | 45 +++++++++++++---------- styles/z-bolt/images/extruder-typeB-3.svg | 45 +++++++++++++---------- styles/z-bolt/images/extruder-typeB-4.svg | 45 +++++++++++++---------- styles/z-bolt/images/extruder-typeB.svg | 44 +++++++++++----------- 5 files changed, 121 insertions(+), 103 deletions(-) mode change 100755 => 100644 styles/z-bolt/images/extruder-typeB-1.svg mode change 100755 => 100644 styles/z-bolt/images/extruder-typeB-2.svg mode change 100755 => 100644 styles/z-bolt/images/extruder-typeB-3.svg mode change 100755 => 100644 styles/z-bolt/images/extruder-typeB-4.svg mode change 100755 => 100644 styles/z-bolt/images/extruder-typeB.svg diff --git a/styles/z-bolt/images/extruder-typeB-1.svg b/styles/z-bolt/images/extruder-typeB-1.svg old mode 100755 new mode 100644 index abff3744..f0c07114 --- a/styles/z-bolt/images/extruder-typeB-1.svg +++ b/styles/z-bolt/images/extruder-typeB-1.svg @@ -4,32 +4,37 @@ - + - + - - + + - + + + + + - - 1 + + 1 diff --git a/styles/z-bolt/images/extruder-typeB-2.svg b/styles/z-bolt/images/extruder-typeB-2.svg old mode 100755 new mode 100644 index b99cb617..0163a86c --- a/styles/z-bolt/images/extruder-typeB-2.svg +++ b/styles/z-bolt/images/extruder-typeB-2.svg @@ -4,32 +4,37 @@ - + - + - - + + - + + + + + - - 2 + + 2 diff --git a/styles/z-bolt/images/extruder-typeB-3.svg b/styles/z-bolt/images/extruder-typeB-3.svg old mode 100755 new mode 100644 index b27be67a..e527c813 --- a/styles/z-bolt/images/extruder-typeB-3.svg +++ b/styles/z-bolt/images/extruder-typeB-3.svg @@ -4,32 +4,37 @@ - + - + - - + + - + + + + + - - 3 + + 3 diff --git a/styles/z-bolt/images/extruder-typeB-4.svg b/styles/z-bolt/images/extruder-typeB-4.svg old mode 100755 new mode 100644 index 49856ebc..0244d042 --- a/styles/z-bolt/images/extruder-typeB-4.svg +++ b/styles/z-bolt/images/extruder-typeB-4.svg @@ -4,32 +4,37 @@ - + - + - - + + - + + + + + - - 4 + + 4 diff --git a/styles/z-bolt/images/extruder-typeB.svg b/styles/z-bolt/images/extruder-typeB.svg old mode 100755 new mode 100644 index 87cc1d5e..f6a86627 --- a/styles/z-bolt/images/extruder-typeB.svg +++ b/styles/z-bolt/images/extruder-typeB.svg @@ -4,33 +4,31 @@ - + - + - - + + - - - - - - 1 + + + From 21c2bcb85003ee40963402682f4b637a6ec0aabb Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 15 Feb 2021 19:17:55 -0800 Subject: [PATCH 37/94] updated version to 2.7.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 Makefile diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index c57acba5..40509c73 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ JESSIE_GO_TAGS := gtk_3_14 # Build information #GIT_COMMIT = $(shell git rev-parse HEAD | cut -c1-7) -VERSION := 2.6.1 +VERSION := 2.7.0 BUILD_DATE ?= $(shell date --utc +%Y%m%d-%H:%M:%S) #BRANCH = $(shell git rev-parse --abbrev-ref HEAD) From 91c41b37cf28be1a87b29f1b2c8a98ffd589f4ab Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 15 Feb 2021 19:26:19 -0800 Subject: [PATCH 38/94] minor format change to open.svg --- styles/z-bolt/images/open.svg | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) mode change 100644 => 100755 styles/z-bolt/images/open.svg diff --git a/styles/z-bolt/images/open.svg b/styles/z-bolt/images/open.svg old mode 100644 new mode 100755 index b8fb6fd9..6d783b79 --- a/styles/z-bolt/images/open.svg +++ b/styles/z-bolt/images/open.svg @@ -3,11 +3,10 @@ - - + - + + - From 9cb31d4059c22ed44c5d2e56f489fbc3ee0cc57d Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 15 Feb 2021 19:29:58 -0800 Subject: [PATCH 39/94] added check to NotificationRequest so it doesn't call the API unless in the splash screen state or in the idle screen state --- octoprintApis/NotificationRequest.go | 8 ++++++-- octoprintApis/OctoScreenSettingsRequest.go | 8 ++++++-- octoprintApis/PluginManagerInfoRequest.go | 8 ++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/octoprintApis/NotificationRequest.go b/octoprintApis/NotificationRequest.go index ff6b2637..df2be2f6 100755 --- a/octoprintApis/NotificationRequest.go +++ b/octoprintApis/NotificationRequest.go @@ -14,9 +14,13 @@ type NotificationRequest struct { Command string `json:"command"` } -func (cmd *NotificationRequest) Do(c *Client) (*dataModels.NotificationResponse, error) { +func (this *NotificationRequest) Do(client *Client, uiState string) (*dataModels.NotificationResponse, error) { + if uiState != "splash" && uiState != "idle" { + return nil, nil + } + target := fmt.Sprintf("%s?command=get_notification", PluginZBoltOctoScreenApiUri) - bytes, err := c.doJsonRequest("GET", target, nil, ConnectionErrors) + bytes, err := client.doJsonRequest("GET", target, nil, ConnectionErrors) if err != nil { return nil, err } diff --git a/octoprintApis/OctoScreenSettingsRequest.go b/octoprintApis/OctoScreenSettingsRequest.go index 5aea65dc..a612a816 100755 --- a/octoprintApis/OctoScreenSettingsRequest.go +++ b/octoprintApis/OctoScreenSettingsRequest.go @@ -3,18 +3,22 @@ package octoprintApis import ( "encoding/json" "fmt" + //"log" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) +// TODO: OctoScreenSettingsRequest seems like it's practically the same as PluginManagerInfoRequest +// Need to clean up and consolidate, or add comments as to why the two different classes. + type OctoScreenSettingsRequest struct { Command string `json:"command"` } -func (cmd *OctoScreenSettingsRequest) Do(c *Client) (*dataModels.OctoScreenSettingsResponse, error) { +func (this *OctoScreenSettingsRequest) Do(client *Client, uiState string) (*dataModels.OctoScreenSettingsResponse, error) { target := fmt.Sprintf("%s?command=get_settings", PluginZBoltOctoScreenApiUri) - bytes, err := c.doJsonRequest("GET", target, nil, ConnectionErrors) + bytes, err := client.doJsonRequest("GET", target, nil, ConnectionErrors) if err != nil { return nil, err } diff --git a/octoprintApis/PluginManagerInfoRequest.go b/octoprintApis/PluginManagerInfoRequest.go index c68eafbc..731190e9 100755 --- a/octoprintApis/PluginManagerInfoRequest.go +++ b/octoprintApis/PluginManagerInfoRequest.go @@ -17,16 +17,16 @@ type PluginManagerInfoRequest struct { } // Do - -func (cmd *PluginManagerInfoRequest) Do(c *Client) (*dataModels.PluginManagerInfoResponse, error) { - cmd.Command = "get_settings" +func (this *PluginManagerInfoRequest) Do(client *Client, uiState string) (*dataModels.PluginManagerInfoResponse, error) { + this.Command = "get_settings" params := bytes.NewBuffer(nil) - if err := json.NewEncoder(params).Encode(cmd); err != nil { + if err := json.NewEncoder(params).Encode(this); err != nil { log.Println("plugin_manager.Do() - Encode() failed") return nil, err } - b, err := c.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) + b, err := client.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) if err != nil { log.Println("plugin_manager.Do() - doJsonRequest() failed") return nil, err From 9e486c058fe714bfe19c1020168feb7dfc5cfcee Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 15 Feb 2021 19:45:04 -0800 Subject: [PATCH 40/94] added support for multi-extruder systems, made desctinction beteween extruders[] and hotends[] --- ui/FilamentPanel.go | 20 +++---- ui/IdleStatusPanel.go | 6 +- ui/PrintStatusPanel.go | 6 +- ui/SystemPanel.go | 2 +- ui/TemperaturePanel.go | 12 ++-- ui/TemperaturePresetsPanel.go | 13 +++-- ui/menu.go | 4 +- ui/tool_changer_panel.go | 4 +- ui/ui.go | 6 +- ui/z_offset_calibration_panel.go | 14 ++--- uiWidgets/CoolDownButton.go | 14 +++-- uiWidgets/FilamentExtrudeButton.go | 8 +-- uiWidgets/FilamentLoadButton.go | 8 +-- uiWidgets/OctoScreenPluginInfoBox.go | 3 +- uiWidgets/SelectToolStepButton.go | 62 ++++++++++++++++++-- uiWidgets/TemperatureIncreaseButton.go | 8 +-- uiWidgets/TemperaturePresetButton.go | 26 +++++++-- uiWidgets/TemperatureStatusBox.go | 2 +- utils/tools.go | 81 ++++++++++++++++++++------ 19 files changed, 209 insertions(+), 90 deletions(-) diff --git a/ui/FilamentPanel.go b/ui/FilamentPanel.go index 9b5a2e38..df7e313e 100755 --- a/ui/FilamentPanel.go +++ b/ui/FilamentPanel.go @@ -29,7 +29,7 @@ type filamentPanel struct { // Third row temperatureButton *gtk.Button - selectToolStepButton *uiWidgets.SelectToolStepButton + selectExtruderStepButton *uiWidgets.SelectToolStepButton } func FilamentPanel( @@ -53,7 +53,7 @@ func (this *filamentPanel) initialize() { // Create the step buttons first, since they are needed by some of the other controls. this.flowRateStepButton = uiWidgets.CreateFlowRateStepButton(this.UI.Client) this.amountToExtrudeStepButton = uiWidgets.CreateAmountToExtrudeStepButton() - this.selectToolStepButton = uiWidgets.CreateSelectToolStepButton(this.UI.Client, false) + this.selectExtruderStepButton = uiWidgets.CreateSelectExtruderStepButton(this.UI.Client, false) // First row @@ -62,7 +62,7 @@ func (this *filamentPanel) initialize() { this.UI.Client, this.amountToExtrudeStepButton, this.flowRateStepButton, - this.selectToolStepButton, + this.selectExtruderStepButton, true, ) this.Grid().Attach(this.filamentExtrudeButton, 0, 0, 1, 1) @@ -76,7 +76,7 @@ func (this *filamentPanel) initialize() { this.UI.Client, this.amountToExtrudeStepButton, this.flowRateStepButton, - this.selectToolStepButton, + this.selectExtruderStepButton, false, ) this.Grid().Attach(this.filamentRetractButton, 3, 0, 1, 1) @@ -87,7 +87,7 @@ func (this *filamentPanel) initialize() { this.UI.window, this.UI.Client, this.flowRateStepButton, - this.selectToolStepButton, + this.selectExtruderStepButton, true, int(this.UI.Settings.FilamentInLength), ) @@ -100,7 +100,7 @@ func (this *filamentPanel) initialize() { this.UI.window, this.UI.Client, this.flowRateStepButton, - this.selectToolStepButton, + this.selectExtruderStepButton, false, int(this.UI.Settings.FilamentOutLength), ) @@ -112,10 +112,10 @@ func (this *filamentPanel) initialize() { this.Grid().Attach(this.temperatureButton, 0, 2, 1, 1) // The select tool step button is needed by some of the other controls (to get the name/ID of the tool - // to send the command to), but only display it if multiple hotends are present. - toolheadCount := utils.GetToolheadCount(this.UI.Client) - if toolheadCount > 1 { - this.Grid().Attach(this.selectToolStepButton, 1, 2, 1, 1) + // to send the command to), but only display it if multiple extruders are present. + extruderCount := utils.GetExtruderCount(this.UI.Client) + if extruderCount > 1 { + this.Grid().Attach(this.selectExtruderStepButton, 1, 2, 1, 1) } } diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go index 64721701..c12ad636 100755 --- a/ui/IdleStatusPanel.go +++ b/ui/IdleStatusPanel.go @@ -76,8 +76,8 @@ func (this *idleStatusPanel) showTools() { // Note: The creation and initialization of the tool buttons in IdleStatusPanel and // PrintStatusPanel look similar, but there are subtle differences between the two // and they can't be reused. - toolheadCount := utils.GetToolheadCount(this.UI.Client) - if toolheadCount == 1 { + hotendCount := utils.GetHotendCount(this.UI.Client) + if hotendCount == 1 { this.tool0Button = uiWidgets.CreateToolButton(0, this.UI.Client) } else { this.tool0Button = uiWidgets.CreateToolButton(1, this.UI.Client) @@ -87,7 +87,7 @@ func (this *idleStatusPanel) showTools() { this.tool3Button = uiWidgets.CreateToolButton( 4, this.UI.Client) this.bedButton = uiWidgets.CreateToolButton(-1, this.UI.Client) - switch toolheadCount { + switch hotendCount { case 1: toolGrid := utils.MustGrid() toolGrid.SetRowHomogeneous(true) diff --git a/ui/PrintStatusPanel.go b/ui/PrintStatusPanel.go index 17084e1c..145877b6 100755 --- a/ui/PrintStatusPanel.go +++ b/ui/PrintStatusPanel.go @@ -71,8 +71,8 @@ func (this *printStatusPanel) showTools() { // Note: The creation and initialization of the tool buttons in IdleStatusPanel and // PrintStatusPanel look similar, but there are subtle differences between the two // and they can't be reused. - toolheadCount := utils.GetToolheadCount(this.UI.Client) - if toolheadCount == 1 { + hotendCount := utils.GetHotendCount(this.UI.Client) + if hotendCount == 1 { this.tool0Button = uiWidgets.CreateToolPrintingButton(0) } else { this.tool0Button = uiWidgets.CreateToolPrintingButton(1) @@ -82,7 +82,7 @@ func (this *printStatusPanel) showTools() { this.tool3Button = uiWidgets.CreateToolPrintingButton( 4) this.bedButton = uiWidgets.CreateToolPrintingButton(-1) - switch toolheadCount { + switch hotendCount { case 1: this.Grid().Attach(this.tool0Button, 0, 0, 2, 1) this.Grid().Attach(this.bedButton, 0, 1, 2, 1) diff --git a/ui/SystemPanel.go b/ui/SystemPanel.go index 9e2ce172..e2979506 100755 --- a/ui/SystemPanel.go +++ b/ui/SystemPanel.go @@ -54,7 +54,7 @@ func (this *systemPanel) initialize() { this.octoScreenInfoBox = uiWidgets.CreateOctoScreenInfoBox(this.UI.Client, OctoScreenVersion) this.Grid().Attach(this.octoScreenInfoBox, 1, 0, 2, 1) - this.octoScreenPluginInfoBox = uiWidgets.CreateOctoScreenPluginInfoBox(this.UI.Client, this.UI.OctoPrintPluginIsAvailable) + this.octoScreenPluginInfoBox = uiWidgets.CreateOctoScreenPluginInfoBox(this.UI.Client, this.UI.UIState, this.UI.OctoPrintPluginIsAvailable) this.Grid().Attach(this.octoScreenPluginInfoBox, 3, 0, 1, 1) diff --git a/ui/TemperaturePanel.go b/ui/TemperaturePanel.go index 27d2cc6d..a7720793 100755 --- a/ui/TemperaturePanel.go +++ b/ui/TemperaturePanel.go @@ -14,7 +14,7 @@ type temperaturePanel struct { // First row decreaseButton *uiWidgets.TemperatureIncreaseButton - selectToolStepButton *uiWidgets.SelectToolStepButton + selectHotendStepButton *uiWidgets.SelectToolStepButton temperatureAmountStepButton *uiWidgets.TemperatureAmountStepButton increaseButton *uiWidgets.TemperatureIncreaseButton @@ -45,26 +45,26 @@ func (this *temperaturePanel) initialize() { // Create the step buttons first, since they are needed by some of the other controls. this.temperatureAmountStepButton = uiWidgets.CreateTemperatureAmountStepButton() - this.selectToolStepButton = uiWidgets.CreateSelectToolStepButton(this.UI.Client, true) + this.selectHotendStepButton = uiWidgets.CreateSelectHotendStepButton(this.UI.Client, true) // First row this.decreaseButton = uiWidgets.CreateTemperatureIncreaseButton( this.UI.Client, this.temperatureAmountStepButton, - this.selectToolStepButton, + this.selectHotendStepButton, false, ) this.Grid().Attach(this.decreaseButton, 0, 0, 1, 1) - this.Grid().Attach(this.selectToolStepButton, 1, 0, 1, 1) + this.Grid().Attach(this.selectHotendStepButton, 1, 0, 1, 1) this.Grid().Attach(this.temperatureAmountStepButton, 2, 0, 1, 1) this.increaseButton = uiWidgets.CreateTemperatureIncreaseButton( this.UI.Client, this.temperatureAmountStepButton, - this.selectToolStepButton, + this.selectHotendStepButton, true, ) this.Grid().Attach(this.increaseButton, 3, 0, 1, 1) @@ -84,6 +84,6 @@ func (this *temperaturePanel) initialize() { } func (this *temperaturePanel) showTemperaturePresetsPanel() { - temperaturePresetsPanel := TemperaturePresetsPanel(this.UI, this, this.selectToolStepButton) + temperaturePresetsPanel := TemperaturePresetsPanel(this.UI, this, this.selectHotendStepButton) this.UI.GoToPanel(temperaturePresetsPanel) } diff --git a/ui/TemperaturePresetsPanel.go b/ui/TemperaturePresetsPanel.go index a335cefe..672b9525 100755 --- a/ui/TemperaturePresetsPanel.go +++ b/ui/TemperaturePresetsPanel.go @@ -12,18 +12,20 @@ var temperaturePresetsPanelInstance *temperaturePresetsPanel type temperaturePresetsPanel struct { CommonPanel - selectToolStepButton *uiWidgets.SelectToolStepButton + + selectHotendStepButton *uiWidgets.SelectToolStepButton + } func TemperaturePresetsPanel( ui *UI, parentPanel interfaces.IPanel, - selectToolStepButton *uiWidgets.SelectToolStepButton, + selectHotendStepButton *uiWidgets.SelectToolStepButton, ) *temperaturePresetsPanel { if temperaturePresetsPanelInstance == nil { instance := &temperaturePresetsPanel { CommonPanel: NewCommonPanel(ui, parentPanel), - selectToolStepButton: selectToolStepButton, + selectHotendStepButton: selectHotendStepButton, } instance.initialize() temperaturePresetsPanelInstance = instance @@ -44,12 +46,14 @@ func (this *temperaturePresetsPanel) createTemperaturePresetButtons() { return } + this.createAllOffButton() + count := 0 for _, temperaturePreset := range settings.Temperature.TemperaturePresets { if count < 10 { temperaturePresetButton := uiWidgets.CreateTemperaturePresetButton( this.UI.Client, - this.selectToolStepButton, + this.selectHotendStepButton, "heat-up.svg", temperaturePreset, this.UI.GoToPreviousPanel, @@ -59,7 +63,6 @@ func (this *temperaturePresetsPanel) createTemperaturePresetButtons() { } } - this.createAllOffButton() } func (this *temperaturePresetsPanel) createAllOffButton() { diff --git a/ui/menu.go b/ui/menu.go index 594edae6..10ceb871 100755 --- a/ui/menu.go +++ b/ui/menu.go @@ -210,8 +210,8 @@ func getDefaultMenuItems(client *octoprintApis.Client) []dataModels.MenuItem { var menuItems []dataModels.MenuItem var err error - toolheadCount := utils.GetToolheadCount(client) - if toolheadCount > 1 { + hotendCount := utils.GetHotendCount(client) + if hotendCount > 1 { err = json.Unmarshal([]byte(defaultMenuItemsForMultipleToolheads), &menuItems) } else { err = json.Unmarshal([]byte(defaultMenuItemsForSingleToolhead), &menuItems) diff --git a/ui/tool_changer_panel.go b/ui/tool_changer_panel.go index 817ca664..59bda907 100755 --- a/ui/tool_changer_panel.go +++ b/ui/tool_changer_panel.go @@ -81,8 +81,8 @@ func (this *toolChangerPanel) createMagnetOffButton() gtk.IWidget { } func (this *toolChangerPanel) createToolheadButtons() { - toolheadCount := utils.GetToolheadCount(this.UI.Client) - toolheadButtons := utils.CreateChangeToolheadButtonsAndAttachToGrid(toolheadCount, this.Grid()) + extruderCount := utils.GetExtruderCount(this.UI.Client) + toolheadButtons := utils.CreateChangeToolheadButtonsAndAttachToGrid(extruderCount, this.Grid()) this.setToolheadButtonClickHandlers(toolheadButtons) } diff --git a/ui/ui.go b/ui/ui.go index 16200bb0..db5058a4 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -271,7 +271,7 @@ func (this *UI) checkNotification() { return } - notificationRespone, err := (&octoprintApis.NotificationRequest{}).Do(this.Client) + notificationRespone, err := (&octoprintApis.NotificationRequest{}).Do(this.Client, this.UIState) if err != nil { utils.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) utils.Logger.Debug("leaving ui.checkNotification()") @@ -288,7 +288,7 @@ func (this *UI) checkNotification() { func (this *UI) loadSettings() { utils.Logger.Debug("entering ui.loadSettings()") - settingsResponse, err := (&octoprintApis.OctoScreenSettingsRequest{}).Do(this.Client) + settingsResponse, err := (&octoprintApis.OctoScreenSettingsRequest{}).Do(this.Client, this.UIState) if err != nil { text := err.Error() if strings.Contains(strings.ToLower(text), "unexpected status code: 404") { @@ -370,7 +370,7 @@ func (this *UI) update() { return } - utils.Logger.Infoln("ui.update() - thus.UIState is: ", this.UIState) + utils.Logger.Infoln("ui.update() - this.UIState is: ", this.UIState) if this.UIState == "splash" { this.connectionAttempts++ diff --git a/ui/z_offset_calibration_panel.go b/ui/z_offset_calibration_panel.go index fddc7a1e..980df54f 100755 --- a/ui/z_offset_calibration_panel.go +++ b/ui/z_offset_calibration_panel.go @@ -29,7 +29,7 @@ type zOffsetCalibrationPanel struct { zOffset float64 // First row - selectToolStepButton *uiWidgets.SelectToolStepButton + selectHotendStepButton *uiWidgets.SelectToolStepButton decreaseZOffsetButton *uiWidgets.IncreaseZOffsetButton increaseZOffsetButton *uiWidgets.IncreaseZOffsetButton @@ -89,21 +89,21 @@ func (this *zOffsetCalibrationPanel) initialize() { // First row func (this *zOffsetCalibrationPanel) CreateSelectToolStepButton() { - this.selectToolStepButton = uiWidgets.CreateSelectToolStepButton(this.UI.Client, false) - _, err := this.selectToolStepButton.Connect("clicked", this.selectToolStepButtonHandleClick) + this.selectHotendStepButton = uiWidgets.CreateSelectHotendStepButton(this.UI.Client, false) + _, err := this.selectHotendStepButton.Connect("clicked", this.selectToolStepButtonHandleClick) if err != nil { panic(err) } - toolheadCount := utils.GetToolheadCount(this.UI.Client) - if toolheadCount > 1 { + hotendCount := utils.GetHotendCount(this.UI.Client) + if hotendCount > 1 { // Only display the select tool button if there are multiple toolheads. - this.Grid().Attach(this.selectToolStepButton, 0, 0, 1, 1) + this.Grid().Attach(this.selectHotendStepButton, 0, 0, 1, 1) } } func (this *zOffsetCalibrationPanel) selectToolStepButtonHandleClick() { - toolheadIndex := this.selectToolStepButton.Index() + toolheadIndex := this.selectHotendStepButton.Index() utils.Logger.Infof("Changing tool to tool%d", toolheadIndex) gcode := fmt.Sprintf("T%d", toolheadIndex) diff --git a/uiWidgets/CoolDownButton.go b/uiWidgets/CoolDownButton.go index f306c354..4eb49aef 100755 --- a/uiWidgets/CoolDownButton.go +++ b/uiWidgets/CoolDownButton.go @@ -47,7 +47,9 @@ func TurnAllHeatersOff( client *octoprintApis.Client, ) { // Set the bed's temp. - bedTargetRequest := &octoprintApis.BedTargetRequest{Target: 0.0} + bedTargetRequest := &octoprintApis.BedTargetRequest { + Target: 0.0, + } err := bedTargetRequest.Do(client) if err != nil { utils.LogError("CoolDownButton.handleClicked()", "Do(BedTargetRequest)", err) @@ -55,9 +57,13 @@ func TurnAllHeatersOff( } // Set the temp of each hotend. - toolheadCount := utils.GetToolheadCount(client) - for i := 0; i < toolheadCount; i++ { - var toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{fmt.Sprintf("tool%d", i): 0.0}} + hotendCount := utils.GetHotendCount(client) + for i := 0; i < hotendCount; i++ { + var toolTargetRequest = &octoprintApis.ToolTargetRequest { + Targets: map[string]float64 { + fmt.Sprintf("tool%d", i): 0.0, + }, + } err = toolTargetRequest.Do(client) if err != nil { utils.LogError("TemperaturePresetsPanel.setTemperaturesToPreset()", "Do(ToolTargetRequest)", err) diff --git a/uiWidgets/FilamentExtrudeButton.go b/uiWidgets/FilamentExtrudeButton.go index 05415ab4..211f4479 100755 --- a/uiWidgets/FilamentExtrudeButton.go +++ b/uiWidgets/FilamentExtrudeButton.go @@ -14,7 +14,7 @@ type FilamentExtrudeButton struct { client *octoprintApis.Client amountToExtrudeStepButton *AmountToExtrudeStepButton flowRateStepButton *FlowRateStepButton // The flow rate step button is optional. - selectToolStepButton *SelectToolStepButton + selectExtruderStepButton *SelectToolStepButton isForward bool } @@ -23,7 +23,7 @@ func CreateFilamentExtrudeButton( client *octoprintApis.Client, amountToExtrudeStepButton *AmountToExtrudeStepButton, flowRateStepButton *FlowRateStepButton, // The flow rate step button is optional. - selectToolStepButton *SelectToolStepButton, + selectExtruderStepButton *SelectToolStepButton, isForward bool, ) *FilamentExtrudeButton { var base *gtk.Button @@ -39,7 +39,7 @@ func CreateFilamentExtrudeButton( client: client, amountToExtrudeStepButton: amountToExtrudeStepButton, flowRateStepButton: flowRateStepButton, - selectToolStepButton: selectToolStepButton, + selectExtruderStepButton: selectExtruderStepButton, isForward: isForward, } _, err := instance.Button.Connect("clicked", instance.handleClicked) @@ -55,7 +55,7 @@ func (this *FilamentExtrudeButton) handleClicked() { } func (this *FilamentExtrudeButton) sendExtrudeCommand(length int) { - extruderId := this.selectToolStepButton.Value() + extruderId := this.selectExtruderStepButton.Value() flowRatePercentage := 100 if this.flowRateStepButton != nil { diff --git a/uiWidgets/FilamentLoadButton.go b/uiWidgets/FilamentLoadButton.go index dadce415..2ea72c00 100755 --- a/uiWidgets/FilamentLoadButton.go +++ b/uiWidgets/FilamentLoadButton.go @@ -16,7 +16,7 @@ type FilamentLoadButton struct { parentWindow *gtk.Window client *octoprintApis.Client flowRateStepButton *FlowRateStepButton // The flow rate step button is optional. - selectToolStepButton *SelectToolStepButton + selectExtruderStepButton *SelectToolStepButton isForward bool length int } @@ -25,7 +25,7 @@ func CreateFilamentLoadButton( parentWindow *gtk.Window, client *octoprintApis.Client, flowRateStepButton *FlowRateStepButton, // The flow rate step button is optional. - selectToolStepButton *SelectToolStepButton, + selectExtruderStepButton *SelectToolStepButton, isForward bool, length int, ) *FilamentLoadButton { @@ -41,7 +41,7 @@ func CreateFilamentLoadButton( parentWindow: parentWindow, client: client, flowRateStepButton: flowRateStepButton, - selectToolStepButton: selectToolStepButton, + selectExtruderStepButton: selectExtruderStepButton, isForward: isForward, length: length, } @@ -58,7 +58,7 @@ func (this *FilamentLoadButton) handleClicked() { } func (this *FilamentLoadButton) sendLoadCommand() { - extruderId := this.selectToolStepButton.Value() + extruderId := this.selectExtruderStepButton.Value() flowRatePercentage := 100 if this.flowRateStepButton != nil { diff --git a/uiWidgets/OctoScreenPluginInfoBox.go b/uiWidgets/OctoScreenPluginInfoBox.go index fd075deb..526ca552 100755 --- a/uiWidgets/OctoScreenPluginInfoBox.go +++ b/uiWidgets/OctoScreenPluginInfoBox.go @@ -14,6 +14,7 @@ type OctoScreenPluginInfoBox struct { func CreateOctoScreenPluginInfoBox( client *octoprintApis.Client, + uiState string, octoPrintPluginIsInstalled bool, ) *OctoScreenPluginInfoBox { logoImage := utils.MustImageFromFile("logos/puzzle-piece.png") @@ -21,7 +22,7 @@ func CreateOctoScreenPluginInfoBox( str2 := "" if octoPrintPluginIsInstalled { - pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client) + pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client, uiState) if err != nil { panic(err) } diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index 69c942eb..95192340 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -14,26 +14,73 @@ type SelectToolStepButton struct { *StepButton } -func CreateSelectToolStepButton( +func CreateSelectExtruderStepButton( client *octoprintApis.Client, includeBed bool, ) *SelectToolStepButton { - toolheadCount := utils.GetToolheadCount(client) + extruderCount := utils.GetExtruderCount(client) var steps []Step - for i := 0; i < toolheadCount; i++ { + for i := 0; i < extruderCount; i++ { var step Step - if i == 0 && toolheadCount == 1 { + if i == 0 && extruderCount == 1 { + step = Step { + "Extruder", + utils.GetExtruderFileName(1, extruderCount), + nil, + "tool0", + } + } else { + step = Step { + fmt.Sprintf("Extruder %d", i + 1), + utils.GetExtruderFileName(i + 1, extruderCount), + nil, + fmt.Sprintf("tool%d", i), + } + } + + steps = append(steps, step) + } + + if includeBed { + steps = append(steps, Step{"Bed", "bed.svg", nil, "bed"}) + } + + base, err := CreateStepButton( + 1, + steps..., + ) + if err != nil { + panic(err) + } + + instance := &SelectToolStepButton{ + StepButton: base, + } + + return instance +} + +func CreateSelectHotendStepButton( + client *octoprintApis.Client, + includeBed bool, +) *SelectToolStepButton { + hotendCount := utils.GetHotendCount(client) + + var steps []Step + for i := 0; i < hotendCount; i++ { + var step Step + if i == 0 && hotendCount == 1 { step = Step { "Hotend", - utils.GetHotendFileName(1, toolheadCount), + utils.GetHotendFileName(1, hotendCount), nil, "tool0", } } else { step = Step { fmt.Sprintf("Hotend %d", i + 1), - utils.GetHotendFileName(i + 1, toolheadCount), + utils.GetHotendFileName(i + 1, hotendCount), nil, fmt.Sprintf("tool%d", i), } @@ -61,6 +108,9 @@ func CreateSelectToolStepButton( return instance } + + + func (this *SelectToolStepButton) Value() string { return this.StepButton.Value().(string) } diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go index 63b12762..fafead78 100755 --- a/uiWidgets/TemperatureIncreaseButton.go +++ b/uiWidgets/TemperatureIncreaseButton.go @@ -12,14 +12,14 @@ type TemperatureIncreaseButton struct { client *octoprintApis.Client temperatureAmountStepButton *TemperatureAmountStepButton - selectToolStepButton *SelectToolStepButton + selectHotendStepButton *SelectToolStepButton isIncrease bool } func CreateTemperatureIncreaseButton( client *octoprintApis.Client, temperatureAmountStepButton *TemperatureAmountStepButton, - selectToolStepButton *SelectToolStepButton, + selectHotendStepButton *SelectToolStepButton, isIncrease bool, ) *TemperatureIncreaseButton { var base *gtk.Button @@ -33,7 +33,7 @@ func CreateTemperatureIncreaseButton( Button: base, client: client, temperatureAmountStepButton: temperatureAmountStepButton, - selectToolStepButton: selectToolStepButton, + selectHotendStepButton: selectHotendStepButton, isIncrease: isIncrease, } _, err := instance.Button.Connect("clicked", instance.handleClicked) @@ -46,7 +46,7 @@ func CreateTemperatureIncreaseButton( func (this *TemperatureIncreaseButton) handleClicked() { value := this.temperatureAmountStepButton.Value() - tool := this.selectToolStepButton.Value() + tool := this.selectHotendStepButton.Value() target, err := utils.GetToolTarget(this.client, tool) if err != nil { utils.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err) diff --git a/uiWidgets/TemperaturePresetButton.go b/uiWidgets/TemperaturePresetButton.go index 651f32fd..8a08c707 100755 --- a/uiWidgets/TemperaturePresetButton.go +++ b/uiWidgets/TemperaturePresetButton.go @@ -11,7 +11,7 @@ type TemperaturePresetButton struct { *gtk.Button client *octoprintApis.Client - selectToolStepButton *SelectToolStepButton + selectHotendStepButton *SelectToolStepButton imageFileName string temperaturePreset *dataModels.TemperaturePreset callback func() @@ -19,7 +19,7 @@ type TemperaturePresetButton struct { func CreateTemperaturePresetButton( client *octoprintApis.Client, - selectToolStepButton *SelectToolStepButton, + selectHotendStepButton *SelectToolStepButton, imageFileName string, temperaturePreset *dataModels.TemperaturePreset, callback func(), @@ -30,7 +30,7 @@ func CreateTemperaturePresetButton( instance := &TemperaturePresetButton{ Button: base, client: client, - selectToolStepButton: selectToolStepButton, + selectHotendStepButton: selectHotendStepButton, imageFileName: imageFileName, temperaturePreset: temperaturePreset, callback: callback, @@ -48,7 +48,7 @@ func (this *TemperaturePresetButton) handleClicked() { utils.Logger.Infof("TemperaturePresetButton.handleClicked() - setting hotend temperature to %.0f.", this.temperaturePreset.Extruder) utils.Logger.Infof("TemperaturePresetButton.handleClicked() - setting bed temperature to %.0f.", this.temperaturePreset.Bed) - currentTool := this.selectToolStepButton.Value() + currentTool := this.selectHotendStepButton.Value() if currentTool == "" { utils.Logger.Error("TemperaturePresetButton.handleClicked() - currentTool is invalid (blank), defaulting to tool0") currentTool = "tool0" @@ -64,6 +64,12 @@ func (this *TemperaturePresetButton) handleClicked() { So, instead, the temperature of both the bed and the selected tool (or tool0 if the bed is selected) are set. + + NOTE: This only changes the temperature of the bed and the currently selected hotend + (which is passed into the TemperaturePresetsPanel, and then passed into + CreateTemperaturePresetButton). The code could be changed so it sets the temperature + of every hotend, but this is problematic if one is using different materials with + different temperature characteristics. */ // Set the bed's temp. @@ -78,9 +84,17 @@ func (this *TemperaturePresetButton) handleClicked() { var toolTargetRequest *octoprintApis.ToolTargetRequest if currentTool == "bed" { // If current tool is set to "bed", use tool0. - toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{"tool0": this.temperaturePreset.Extruder}} + toolTargetRequest = &octoprintApis.ToolTargetRequest { + Targets: map[string]float64 { + "tool0": this.temperaturePreset.Extruder, + }, + } } else { - toolTargetRequest = &octoprintApis.ToolTargetRequest{Targets: map[string]float64{currentTool: this.temperaturePreset.Extruder}} + toolTargetRequest = &octoprintApis.ToolTargetRequest { + Targets: map[string]float64 { + currentTool: this.temperaturePreset.Extruder, + }, + } } err = toolTargetRequest.Do(this.client) diff --git a/uiWidgets/TemperatureStatusBox.go b/uiWidgets/TemperatureStatusBox.go index 15ed01d8..fd2b8623 100755 --- a/uiWidgets/TemperatureStatusBox.go +++ b/uiWidgets/TemperatureStatusBox.go @@ -47,7 +47,7 @@ func CreateTemperatureStatusBox( var bedTemperatureData *dataModels.TemperatureData = nil var hotendIndex int = 0 - var hotendCount int = utils.GetToolheadCount(client) + var hotendCount int = utils.GetHotendCount(client) for key, temperatureData := range currentTemperatureData { if key == "bed" { bedTemperatureData = &temperatureData diff --git a/utils/tools.go b/utils/tools.go index ed547c71..c67825b2 100755 --- a/utils/tools.go +++ b/utils/tools.go @@ -10,43 +10,72 @@ import ( "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) -var cachedToolheadCount = -1 +var cachedExtruderCount = -1 +var cachedHasSharedNozzle = false -func GetToolheadCount(client *octoprintApis.Client) int { - if cachedToolheadCount != -1 { - return cachedToolheadCount +func getCachedPrinterProfileData(client *octoprintApis.Client) { + if cachedExtruderCount != -1 { + return } connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(client) if err != nil { - LogError("Tools.GetToolheadCount()", "version.Get()", err) - return 0 + LogError("Tools.setCachedPrinterProfileData()", "version.Get()", err) + return } printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(client) if err != nil { - LogError("Tools.GetToolheadCount()", "Do(PrinterProfilesRequest)", err) - return 0 + LogError("Tools.setCachedPrinterProfileData()", "Do(PrinterProfilesRequest)", err) + return } - cachedToolheadCount = printerProfile.Extruder.Count - if printerProfile.Extruder.HasSharedNozzle { - cachedToolheadCount = 1 - } else if cachedToolheadCount > 4 { - cachedToolheadCount = 4 + cachedExtruderCount = printerProfile.Extruder.Count + if cachedExtruderCount > 4 { + cachedExtruderCount = 4 } + cachedHasSharedNozzle = printerProfile.Extruder.HasSharedNozzle +} + + +func GetExtruderCount(client *octoprintApis.Client) int { + if cachedExtruderCount == -1 { + getCachedPrinterProfileData(client) + } + + return cachedExtruderCount +} + +func GetHotendCount(client *octoprintApis.Client) int { + if cachedExtruderCount == -1 { + getCachedPrinterProfileData(client) + } - // TESTING: uncomment to force all toolheads to display and use for testing - // cachedToolheadCount = 2 - // cachedToolheadCount = 3 - // cachedToolheadCount = 4 + if cachedHasSharedNozzle { + return 1 + } else if cachedExtruderCount > 4 { + return 4 + } + + return cachedExtruderCount +} +func GetHasSharedNozzle(client *octoprintApis.Client) bool { + if cachedExtruderCount == -1 { + getCachedPrinterProfileData(client) + } - return cachedToolheadCount + return cachedHasSharedNozzle } + + + + + + func GetDisplayNameForTool(toolName string) string { // Since this is such a hack, lets add some bounds checking if toolName == "" { @@ -183,6 +212,18 @@ func GetToolheadFileName(hotendIndex, hotendCount int) string { return strImageFileName } + +func GetExtruderFileName(hotendIndex, hotendCount int) string { + strImageFileName := "" + if hotendIndex == 1 && hotendCount == 1 { + strImageFileName = "extruder-typeB.svg" + } else { + strImageFileName = fmt.Sprintf("extruder-typeB-%d.svg", hotendIndex) + } + + return strImageFileName +} + func GetHotendFileName(hotendIndex, hotendCount int) string { strImageFileName := "" if hotendIndex == 1 && hotendCount == 1 { @@ -194,6 +235,10 @@ func GetHotendFileName(hotendIndex, hotendCount int) string { return strImageFileName } + + + + func GetNozzleFileName(hotendIndex, hotendCount int) string { strImageFileName := "" if hotendIndex == 1 && hotendCount == 1 { From 56dc6c7873f5648b91376502584fc1c9d78eee3e Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Wed, 17 Feb 2021 18:03:20 -0800 Subject: [PATCH 41/94] added additional log statements for debugging --- octoprintApis/client.go | 6 ++--- octoprintApis/system.go | 2 +- octoprintApis/version.go | 8 +++---- ui/IdleStatusPanel.go | 40 +++++++++++++++++++++++++++++--- ui/SplashPanel.go | 32 +++++++++++++++++++++++-- ui/ui.go | 21 ++++++++++------- ui/z_offset_calibration_panel.go | 4 ++++ 7 files changed, 92 insertions(+), 21 deletions(-) diff --git a/octoprintApis/client.go b/octoprintApis/client.go index 1e67ac30..e3722dc8 100755 --- a/octoprintApis/client.go +++ b/octoprintApis/client.go @@ -35,12 +35,12 @@ type Client struct { // `Access Control` is enabled at OctoPrint configuration an apiKey should be // provided (http://docs.octoprint.org/en/master/api/general.html#authorization). func NewClient(endpoint, apiKey string) *Client { - return &Client{ + return &Client { Endpoint: endpoint, APIKey: apiKey, - httpClient: &http.Client{ + httpClient: &http.Client { Timeout: time.Second * 3, - Transport: &http.Transport{ + Transport: &http.Transport { DisableKeepAlives: true, }, }, diff --git a/octoprintApis/system.go b/octoprintApis/system.go index 80063f73..7e08c934 100755 --- a/octoprintApis/system.go +++ b/octoprintApis/system.go @@ -28,7 +28,7 @@ func (cmd *SystemCommandsRequest) Do(c *Client) (*dataModels.SystemCommandsRespo } // TODO: there are 2 warnings here... the 2nd parameter into Unmarshal() - // is supposed to be a point. Change x.Confirm to &x.Confirm ? + // is supposed to be a pointer. Change x.Confirm to &x.Confirm ? // need to verify r := &dataModels.SystemCommandsResponse{} diff --git a/octoprintApis/version.go b/octoprintApis/version.go index f1e01202..d275f184 100755 --- a/octoprintApis/version.go +++ b/octoprintApis/version.go @@ -15,15 +15,15 @@ type VersionRequest struct{} // Do sends an API request and returns the API response. func (cmd *VersionRequest) Do(c *Client) (*dataModels.VersionResponse, error) { - b, err := c.doJsonRequest("GET", VersionApiUri, nil, nil) + bytes, err := c.doJsonRequest("GET", VersionApiUri, nil, nil) if err != nil { return nil, err } - r := &dataModels.VersionResponse{} - if err := json.Unmarshal(b, r); err != nil { + response := &dataModels.VersionResponse{} + if err := json.Unmarshal(bytes, response); err != nil { return nil, err } - return r, err + return response, err } diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go index c12ad636..2ed05b86 100755 --- a/ui/IdleStatusPanel.go +++ b/ui/IdleStatusPanel.go @@ -1,6 +1,7 @@ package ui import ( + // "encoding/json" // "fmt" // "sync" "time" @@ -11,6 +12,7 @@ import ( "github.com/Z-Bolt/OctoScreen/utils" ) + var idleStatusPanelInstance *idleStatusPanel type idleStatusPanel struct { @@ -38,16 +40,34 @@ func IdleStatusPanel(ui *UI) *idleStatusPanel { } func (this *idleStatusPanel) initialize() { + utils.Logger.Debug("entering IdleStatusPanel.initialize()") + defer this.Initialize() - utils.Logger.Info(this.UI.Settings) + utils.Logger.Info("IdleStatusPanel.initialize() - settings are:") + if this.UI == nil { + utils.Logger.Error("IdleStatusPanel.initialize() - this.UI is nil") + } else if this.UI.Settings == nil { + utils.Logger.Error("IdleStatusPanel.initialize() - this.UI.Settings is nil") + } else { + utils.Logger.Info("struct values:") + utils.Logger.Info(this.UI.Settings) + + jsonStr, err := utils.StructToJson(this.UI.Settings) + if err == nil { + utils.Logger.Info("JSON:") + utils.Logger.Info(jsonStr) + } + } + utils.Logger.Info("") + utils.Logger.Info("") var menuItems []dataModels.MenuItem if this.UI.Settings == nil || this.UI.Settings.MenuStructure == nil || len(this.UI.Settings.MenuStructure) < 1 { - utils.Logger.Info("Loading default menu") + utils.Logger.Info("IdleStatusPanel.initialize() - Loading default menu") this.UI.Settings.MenuStructure = getDefaultMenuItems(this.UI.Client) } else { - utils.Logger.Info("Loading octo menu") + utils.Logger.Info("IdleStatusPanel.initialize() - Loading octo menu") } menuItems = this.UI.Settings.MenuStructure @@ -62,17 +82,29 @@ func (this *idleStatusPanel) initialize() { this.Grid().Attach(printButton, 2, 2, 2, 1) this.showTools() + + utils.Logger.Debug("leaving IdleStatusPanel.initialize()") } func (this *idleStatusPanel) showFiles() { + utils.Logger.Debug("entering IdleStatusPanel.showFiles()") + this.UI.GoToPanel(FilesPanel(this.UI, this)) + + utils.Logger.Debug("leaving IdleStatusPanel.showFiles()") } func (this *idleStatusPanel) update() { + utils.Logger.Debug("entering IdleStatusPanel.update()") + this.updateTemperature() + + utils.Logger.Debug("leaving IdleStatusPanel.update()") } func (this *idleStatusPanel) showTools() { + utils.Logger.Debug("entering IdleStatusPanel.showTools()") + // Note: The creation and initialization of the tool buttons in IdleStatusPanel and // PrintStatusPanel look similar, but there are subtle differences between the two // and they can't be reused. @@ -114,6 +146,8 @@ func (this *idleStatusPanel) showTools() { this.Grid().Attach(this.tool3Button, 1, 1, 1, 1) this.Grid().Attach(this.bedButton, 0, 2, 2, 1) } + + utils.Logger.Debug("leaving IdleStatusPanel.showTools()") } func (this *idleStatusPanel) updateTemperature() { diff --git a/ui/SplashPanel.go b/ui/SplashPanel.go index 00b7ff6d..acb2e1d2 100755 --- a/ui/SplashPanel.go +++ b/ui/SplashPanel.go @@ -22,6 +22,8 @@ func NewSplashPanel(ui *UI) *SplashPanel { } func (this *SplashPanel) initialize() { + utils.Logger.Debug("entering SplashPanel.initialize()") + logo := utils.MustImageFromFile("logos/logo.png") this.Label = utils.MustLabel("...") this.Label.SetHExpand(true) @@ -45,9 +47,13 @@ func (this *SplashPanel) initialize() { box.Add(this.createActionBar()) this.Grid().Add(box) + + utils.Logger.Debug("leaving SplashPanel.initialize()") } func (this *SplashPanel) createActionBar() gtk.IWidget { + utils.Logger.Debug("entering SplashPanel.createActionBar()") + actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) actionBar.SetHAlign(gtk.ALIGN_END) @@ -66,29 +72,51 @@ func (this *SplashPanel) createActionBar() gtk.IWidget { networkButton.SetProperty("width-request", this.Scaled(100)) actionBar.Add(networkButton) + utils.Logger.Debug("leaving SplashPanel.createActionBar()") + return actionBar } func (this *SplashPanel) putOnHold() { + utils.Logger.Debug("entering SplashPanel.putOnHold()") + this.RetryButton.Show() - ctx, _ := this.RetryButton.GetStyleContext() - ctx.RemoveClass("hidden") + ctx, err := this.RetryButton.GetStyleContext() + if err != nil { + utils.LogError("SplashPanel.putOnHold()", "RetryButton.GetStyleContext()", err) + } else { + ctx.RemoveClass("hidden") + } this.Label.SetText("Cannot connect to the printer. Tap \"Retry\" to try again.") + + utils.Logger.Debug("leaving SplashPanel.putOnHold()") } func (this *SplashPanel) releaseFromHold() { + utils.Logger.Debug("entering SplashPanel.releaseFromHold()") + this.RetryButton.Hide() ctx, _ := this.RetryButton.GetStyleContext() ctx.AddClass("hidden") this.Label.SetText("Loading...") this.UI.connectionAttempts = 0 + + utils.Logger.Debug("leaving SplashPanel.releaseFromHold()") } func (this *SplashPanel) showNetwork() { + utils.Logger.Debug("entering SplashPanel.showNetwork()") + this.UI.GoToPanel(NetworkPanel(this.UI, this)) + + utils.Logger.Debug("leaving SplashPanel.showNetwork()") } func (this *SplashPanel) showSystem() { + utils.Logger.Debug("entering SplashPanel.showSystem()") + this.UI.GoToPanel(SystemPanel(this.UI, this)) + + utils.Logger.Debug("leaving SplashPanel.showSystem()") } diff --git a/ui/ui.go b/ui/ui.go index db5058a4..41c62bb3 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -10,6 +10,7 @@ import ( "github.com/golang-collections/collections/stack" "github.com/gotk3/gotk3/gdk" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/interfaces" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" @@ -201,7 +202,7 @@ func (this *UI) verifyConnection() { } } } else { - utils.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest)", err) + utils.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err) utils.Logger.Info("ui.verifyConnection() - now setting newUIState to 'splash'") newUIState = "splash" @@ -212,8 +213,11 @@ func (this *UI) verifyConnection() { utils.Logger.Infof("ui.verifyConnection() - errMessage is: %q", errMessage) if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") { - // Use 'offline' here, but no ending period. - splashMessage = "Printer is OFFLINE" + utils.Logger.Errorf("ui.verifyConnection() - %s", errMessage) + splashMessage = "Printer is offline (deadline exceeded)" + } else if strings.Contains(strings.ToLower(errMessage), "connection reset by peer") { + utils.Logger.Errorf("ui.verifyConnection() - %s", errMessage) + splashMessage = "Printer is offline (peer connection reset)" } else { splashMessage = errMessage } @@ -271,15 +275,15 @@ func (this *UI) checkNotification() { return } - notificationRespone, err := (&octoprintApis.NotificationRequest{}).Do(this.Client, this.UIState) + notificationResponse, err := (&octoprintApis.NotificationRequest{}).Do(this.Client, this.UIState) if err != nil { utils.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) utils.Logger.Debug("leaving ui.checkNotification()") return } - if notificationRespone.Message != "" { - utils.InfoMessageDialogBox(this.window, notificationRespone.Message) + if notificationResponse != nil && notificationResponse.Message != "" { + utils.InfoMessageDialogBox(this.window, notificationResponse.Message) } utils.Logger.Debug("leaving ui.checkNotification()") @@ -370,7 +374,7 @@ func (this *UI) update() { return } - utils.Logger.Infoln("ui.update() - this.UIState is: ", this.UIState) + utils.Logger.Infof("ui.update() - this.UIState is: %q", this.UIState) if this.UIState == "splash" { this.connectionAttempts++ @@ -494,5 +498,6 @@ func (this *UI) errToUser(err error) string { } utils.Logger.Debugf("leaving ui.errToUser() - unexpected error: %q", text) - return fmt.Sprintf("Unexpected error: %s", err) + + return fmt.Sprintf("Unexpected Error: %s", text) } diff --git a/ui/z_offset_calibration_panel.go b/ui/z_offset_calibration_panel.go index 980df54f..c4e2a595 100755 --- a/ui/z_offset_calibration_panel.go +++ b/ui/z_offset_calibration_panel.go @@ -92,6 +92,7 @@ func (this *zOffsetCalibrationPanel) CreateSelectToolStepButton() { this.selectHotendStepButton = uiWidgets.CreateSelectHotendStepButton(this.UI.Client, false) _, err := this.selectHotendStepButton.Connect("clicked", this.selectToolStepButtonHandleClick) if err != nil { + utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateSelectToolStepButton()", "selectHotendStepButton.Connect()", err) panic(err) } @@ -132,6 +133,7 @@ func (this *zOffsetCalibrationPanel) CreateDecreaseZOffsetButton() { this.decreaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(false) _, err := this.decreaseZOffsetButton.Connect("clicked", this.decreaseZOffsetButtonClicked) if err != nil { + utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateDecreaseZOffsetButton()", "decreaseZOffsetButton.Connect()", err) panic(err) } this.Grid().Attach(this.decreaseZOffsetButton, 1, 0, 1, 1) @@ -149,6 +151,7 @@ func (this *zOffsetCalibrationPanel) CreateIncreaseZOffsetButton() { this.increaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(true) _, err := this.increaseZOffsetButton.Connect("clicked", this.increaseZOffsetButtonClicked) if err != nil { + utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateIncreaseZOffsetButton()", "increaseZOffsetButton.Connect()", err) panic(err) } this.Grid().Attach(this.increaseZOffsetButton, 2, 0, 1, 1) @@ -182,6 +185,7 @@ func (this *zOffsetCalibrationPanel) CreateManualZCalibrationStepButton() { this.manualZCalibrationStepButton = uiWidgets.CreateManualZCalibrationStepButton() _, err := this.manualZCalibrationStepButton.Connect("clicked", this.manualZCalibrationStepButtonHandleClick) if err != nil { + utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateManualZCalibrationStepButton()", "manualZCalibrationStepButton.Connect()", err) panic(err) } From 30dc19303fc547f2954fd482d8a6f38b559fdf2f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Wed, 17 Feb 2021 18:06:32 -0800 Subject: [PATCH 42/94] added additional log statements for debugging --- uiWidgets/AmountToExtrudeStepButton.go | 2 ++ uiWidgets/AmountToMoveStepButton.go | 2 ++ uiWidgets/CommandButton.go | 1 + uiWidgets/ControlButton.go | 1 + uiWidgets/CoolDownButton.go | 1 + uiWidgets/FanButton.go | 1 + uiWidgets/FilamentExtrudeButton.go | 1 + uiWidgets/FilamentLoadButton.go | 1 + uiWidgets/FlowRateStepButton.go | 1 + uiWidgets/HomeAllButton.go | 1 + uiWidgets/HomeButton.go | 1 + uiWidgets/ManualZCalibrationStepButton.go | 2 ++ uiWidgets/MustPressedButton.go | 7 +++--- uiWidgets/OctoPrintInfoBox.go | 15 ++++++++---- uiWidgets/OctoScreenPluginInfoBox.go | 29 ++++++++++++----------- uiWidgets/SelectToolStepButton.go | 2 ++ uiWidgets/StepButton.go | 1 + uiWidgets/SystemCommandButton.go | 1 + uiWidgets/TemperatureAmountStepButton.go | 2 ++ uiWidgets/TemperatureIncreaseButton.go | 1 + uiWidgets/TemperaturePresetButton.go | 1 + 21 files changed, 53 insertions(+), 21 deletions(-) diff --git a/uiWidgets/AmountToExtrudeStepButton.go b/uiWidgets/AmountToExtrudeStepButton.go index 758bdb58..c84a6b7e 100755 --- a/uiWidgets/AmountToExtrudeStepButton.go +++ b/uiWidgets/AmountToExtrudeStepButton.go @@ -1,6 +1,7 @@ package uiWidgets import ( + "github.com/Z-Bolt/OctoScreen/utils" ) type AmountToExtrudeStepButton struct { @@ -18,6 +19,7 @@ func CreateAmountToExtrudeStepButton() *AmountToExtrudeStepButton { Step{" 10mm", "move-step.svg", nil, 10}, ) if err != nil { + utils.LogError("PANIC!!! - CreateAmountToExtrudeStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/AmountToMoveStepButton.go b/uiWidgets/AmountToMoveStepButton.go index 8613c1d5..42b1d636 100755 --- a/uiWidgets/AmountToMoveStepButton.go +++ b/uiWidgets/AmountToMoveStepButton.go @@ -1,6 +1,7 @@ package uiWidgets import ( + "github.com/Z-Bolt/OctoScreen/utils" ) type AmountToMoveStepButton struct { @@ -18,6 +19,7 @@ func CreateAmountToMoveStepButton() *AmountToMoveStepButton { Step{" 1mm", "move-step.svg", nil, 1.00}, ) if err != nil { + utils.LogError("PANIC!!! - CreateAmountToMoveStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index 0db7cfaa..1488a1dc 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -32,6 +32,7 @@ func CreateCommandButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateCommandButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index a765376f..aa6b8231 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -32,6 +32,7 @@ func CreateControlButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateControlButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/CoolDownButton.go b/uiWidgets/CoolDownButton.go index 4eb49aef..59c4f413 100755 --- a/uiWidgets/CoolDownButton.go +++ b/uiWidgets/CoolDownButton.go @@ -29,6 +29,7 @@ func CreateCoolDownButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateCoolDownButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FanButton.go b/uiWidgets/FanButton.go index 24ca50eb..dd7f3e4f 100755 --- a/uiWidgets/FanButton.go +++ b/uiWidgets/FanButton.go @@ -41,6 +41,7 @@ func CreateFanButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateFanButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FilamentExtrudeButton.go b/uiWidgets/FilamentExtrudeButton.go index 211f4479..01af4896 100755 --- a/uiWidgets/FilamentExtrudeButton.go +++ b/uiWidgets/FilamentExtrudeButton.go @@ -44,6 +44,7 @@ func CreateFilamentExtrudeButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateFilamentExtrudeButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FilamentLoadButton.go b/uiWidgets/FilamentLoadButton.go index 2ea72c00..1d46e83e 100755 --- a/uiWidgets/FilamentLoadButton.go +++ b/uiWidgets/FilamentLoadButton.go @@ -47,6 +47,7 @@ func CreateFilamentLoadButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateFilamentLoadButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FlowRateStepButton.go b/uiWidgets/FlowRateStepButton.go index 36deefc7..3144d31f 100755 --- a/uiWidgets/FlowRateStepButton.go +++ b/uiWidgets/FlowRateStepButton.go @@ -21,6 +21,7 @@ func CreateFlowRateStepButton( Step{"Slow (75%)", "speed-slow.svg", nil, 75}, ) if err != nil { + utils.LogError("PANIC!!! - CreateFlowRateStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/HomeAllButton.go b/uiWidgets/HomeAllButton.go index 1c270d9b..630580a0 100755 --- a/uiWidgets/HomeAllButton.go +++ b/uiWidgets/HomeAllButton.go @@ -24,6 +24,7 @@ func CreateHomeAllButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateHomeAllButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/HomeButton.go b/uiWidgets/HomeButton.go index 83ce0764..09ba202b 100755 --- a/uiWidgets/HomeButton.go +++ b/uiWidgets/HomeButton.go @@ -29,6 +29,7 @@ func CreateHomeButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateHomeButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/ManualZCalibrationStepButton.go b/uiWidgets/ManualZCalibrationStepButton.go index ed2d099a..833657f0 100755 --- a/uiWidgets/ManualZCalibrationStepButton.go +++ b/uiWidgets/ManualZCalibrationStepButton.go @@ -1,6 +1,7 @@ package uiWidgets import ( + "github.com/Z-Bolt/OctoScreen/utils" ) type ManualZCalibrationStepButton struct { @@ -14,6 +15,7 @@ func CreateManualZCalibrationStepButton() *ManualZCalibrationStepButton { Step{"Stop Manual\nZ Calibration", "z-calibration.svg", nil, true}, ) if err != nil { + utils.LogError("PANIC!!! - CreateManualZCalibrationStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/MustPressedButton.go b/uiWidgets/MustPressedButton.go index da5bb707..88dee82f 100755 --- a/uiWidgets/MustPressedButton.go +++ b/uiWidgets/MustPressedButton.go @@ -18,9 +18,10 @@ func MustPressedButton( isReleased := make(chan bool) var mutex sync.Mutex - button, error := gtk.ButtonNewWithLabel(label) - if error != nil { - panic(error) + button, err := gtk.ButtonNewWithLabel(label) + if err != nil { + utils.LogError("PANIC!!! - MustPressedButton()", "gtk.ButtonNewWithLabel()", err) + panic(err) } button.SetImage(image) diff --git a/uiWidgets/OctoPrintInfoBox.go b/uiWidgets/OctoPrintInfoBox.go index e22ea076..68f7395a 100755 --- a/uiWidgets/OctoPrintInfoBox.go +++ b/uiWidgets/OctoPrintInfoBox.go @@ -21,18 +21,25 @@ func CreateOctoPrintInfoBox( logoHeight := int(float64(logoWidth) * 1.25) logoImage := utils.MustImageFromFileWithSize("logos/logo-octoprint.png", logoWidth, logoHeight) + server := "" + apiVersion := "" versionResponse, err := (&octoprintApis.VersionRequest{}).Do(client) if err != nil { - // TODO: should the error really trigger a panic? - panic(err) + utils.LogError("OctoPrintInfoBox.CreateOctoPrintInfoBox()", "VersionRequest.Do()", err) + } else if versionResponse == nil { + server = "Unknown?" + apiVersion = "Unknown?" + } else { + server = versionResponse.Server + apiVersion = versionResponse.API } base := CreateSystemInfoBox( client, logoImage, "OctoPrint", - versionResponse.Server, - fmt.Sprintf("(API %s)", versionResponse.API), // Use 3 spaces... 1 space doesn't have enough kerning. + server, + fmt.Sprintf("(API %s)", apiVersion), // Use 3 spaces... 1 space doesn't have enough kerning. ) instance := &OctoPrintInfoBox { diff --git a/uiWidgets/OctoScreenPluginInfoBox.go b/uiWidgets/OctoScreenPluginInfoBox.go index 526ca552..1ea8389e 100755 --- a/uiWidgets/OctoScreenPluginInfoBox.go +++ b/uiWidgets/OctoScreenPluginInfoBox.go @@ -24,22 +24,23 @@ func CreateOctoScreenPluginInfoBox( if octoPrintPluginIsInstalled { pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client, uiState) if err != nil { - panic(err) - } - - found := false - for i := 0; i < len(pluginManagerInfoResponse.Plugins) && !found; i++ { - plugin := pluginManagerInfoResponse.Plugins[i] - if plugin.Key == "zbolt_octoscreen" { - found = true - str2 = plugin.Version + utils.LogError("CreateOctoScreenPluginInfoBox()", "PluginManagerInfoRequest.Do()", err) + str2 = "Error" + } else { + found := false + for i := 0; i < len(pluginManagerInfoResponse.Plugins) && !found; i++ { + plugin := pluginManagerInfoResponse.Plugins[i] + if plugin.Key == "zbolt_octoscreen" { + found = true + str2 = plugin.Version + } } - } - if !found { - // OK, the plugin is there, we just can't get the info from a GET request. - // Default to displaying, "Present" - str2 = "Present" + if !found { + // OK, the plugin is there, we just can't get the info from a GET request. + // Default to displaying, "Present" + str2 = "Present" + } } } else { str2 = "Not installed" diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index 95192340..acd2964a 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -51,6 +51,7 @@ func CreateSelectExtruderStepButton( steps..., ) if err != nil { + utils.LogError("PANIC!!! - CreateSelectExtruderStepButton()", "CreateStepButton()", err) panic(err) } @@ -98,6 +99,7 @@ func CreateSelectHotendStepButton( steps..., ) if err != nil { + utils.LogError("PANIC!!! - CreateSelectHotendStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/StepButton.go b/uiWidgets/StepButton.go index 0269f653..9750c5ce 100755 --- a/uiWidgets/StepButton.go +++ b/uiWidgets/StepButton.go @@ -26,6 +26,7 @@ type StepButton struct { func CreateStepButton(colorVariation int, steps ...Step) (*StepButton, error) { if len(steps) < 1 { + utils.Logger.Error("PANIC!!! - CreateStepButton() - len(steps) < 1") panic("StepButton.CreateStepButton() - steps is empty") } diff --git a/uiWidgets/SystemCommandButton.go b/uiWidgets/SystemCommandButton.go index c80f9a49..0a0fd900 100755 --- a/uiWidgets/SystemCommandButton.go +++ b/uiWidgets/SystemCommandButton.go @@ -22,6 +22,7 @@ func CreateSystemCommandButton( ) *SystemCommandButton { systemCommandsResponse, err := (&octoprintApis.SystemCommandsRequest{}).Do(client) if err != nil { + utils.LogError("PANIC!!! - CreateSystemCommandButton()", "SystemCommandsRequest.Do()", err) panic(err) } diff --git a/uiWidgets/TemperatureAmountStepButton.go b/uiWidgets/TemperatureAmountStepButton.go index 72529e28..69633934 100755 --- a/uiWidgets/TemperatureAmountStepButton.go +++ b/uiWidgets/TemperatureAmountStepButton.go @@ -1,6 +1,7 @@ package uiWidgets import ( + "github.com/Z-Bolt/OctoScreen/utils" ) type TemperatureAmountStepButton struct { @@ -17,6 +18,7 @@ func CreateTemperatureAmountStepButton() *TemperatureAmountStepButton { Step{" 5°C", "move-step.svg", nil, 5.0}, ) if err != nil { + utils.LogError("PANIC!!! - CreateTemperatureAmountStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go index fafead78..673eef7d 100755 --- a/uiWidgets/TemperatureIncreaseButton.go +++ b/uiWidgets/TemperatureIncreaseButton.go @@ -38,6 +38,7 @@ func CreateTemperatureIncreaseButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateTemperatureIncreaseButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/TemperaturePresetButton.go b/uiWidgets/TemperaturePresetButton.go index 8a08c707..03f1eb09 100755 --- a/uiWidgets/TemperaturePresetButton.go +++ b/uiWidgets/TemperaturePresetButton.go @@ -37,6 +37,7 @@ func CreateTemperaturePresetButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { + utils.LogError("PANIC!!! - CreateTemperaturePresetButton()", "instance.Button.Connect()", err) panic(err) } From 380e688fb58c99b4b1eea19cbee9fbd3a28be834 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Wed, 17 Feb 2021 18:07:59 -0800 Subject: [PATCH 43/94] added additional log statements for debugging --- utils/LocationHistory.go | 3 ++- utils/gtk.go | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go index f4836c77..e90f06aa 100755 --- a/utils/LocationHistory.go +++ b/utils/LocationHistory.go @@ -20,7 +20,8 @@ func (this *LocationHistory) Length() int { func (this *LocationHistory) CurrentLocation() dataModels.Location { length := this.Length() if length < 1 { - panic("LocationHistory.current() - locations is empty") + log.Error("CurrentLocation() - length < 1") + panic("PANIC!!! - LocationHistory.current() - locations is empty") } return this.Locations[length - 1] diff --git a/utils/gtk.go b/utils/gtk.go index e813352d..e1dee49d 100755 --- a/utils/gtk.go +++ b/utils/gtk.go @@ -15,6 +15,7 @@ import ( func MustWindow(windowType gtk.WindowType) *gtk.Window { win, err := gtk.WindowNew(windowType) if err != nil { + LogError("PANIC!!! - MustWindow()", "gtk.WindowNew()", err) panic(err) } @@ -27,6 +28,7 @@ func MustWindow(windowType gtk.WindowType) *gtk.Window { func MustGrid() *gtk.Grid { grid, err := gtk.GridNew() if err != nil { + LogError("PANIC!!! - MustGrid()", "gtk.GridNew()", err) panic(err) } @@ -37,6 +39,7 @@ func MustGrid() *gtk.Grid { func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box { box, err := gtk.BoxNew(orientation, spacing) if err != nil { + LogError("PANIC!!! - MustBox()", "gtk.BoxNew()", err) panic(err) } @@ -47,6 +50,7 @@ func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box { func MustProgressBar() *gtk.ProgressBar { progressBar, err := gtk.ProgressBarNew() if err != nil { + LogError("PANIC!!! - MustProgressBar()", "gtk.ProgressBarNew()", err) panic(err) } @@ -57,6 +61,7 @@ func MustProgressBar() *gtk.ProgressBar { func MustLabel(format string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { + LogError("PANIC!!! - MustLabel()", "gtk.LabelNew()", err) panic(err) } @@ -69,6 +74,7 @@ func MustLabel(format string, args ...interface{}) *gtk.Label { func MustLabelWithCssClass(format string, className string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { + LogError("PANIC!!! - MustLabelWithCssClass()", "gtk.LabelNew()", err) panic(err) } @@ -84,6 +90,7 @@ func MustLabelWithCssClass(format string, className string, args ...interface{}) func MustLabelWithCssClasses(format string, classNames []string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { + LogError("PANIC!!! - MustLabelWithCssClasses()", "gtk.LabelNew()", err) panic(err) } @@ -130,6 +137,7 @@ func MustButtonImage(buttonlabel, imageFileName string, clicked func()) *gtk.But image := MustImageFromFile(imageFileName) button, err := gtk.ButtonNewWithLabel(buttonlabel) if err != nil { + LogError("PANIC!!! - MustButtonImage()", "gtk.ButtonNewWithLabel()", err) panic(err) } @@ -150,6 +158,7 @@ func MustToggleButton(label string, imageFileName string, clicked func()) *gtk.T image := MustImageFromFile(imageFileName) button, err := gtk.ToggleButtonNewWithLabel(label) if err != nil { + LogError("PANIC!!! - MustToggleButton()", "gtk.ToggleButtonNewWithLabel()", err) panic(err) } @@ -169,6 +178,7 @@ func MustToggleButton(label string, imageFileName string, clicked func()) *gtk.T func MustButton(image *gtk.Image, clicked func()) *gtk.Button { button, err := gtk.ButtonNew() if err != nil { + LogError("PANIC!!! - MustButton()", "gtk.ButtonNew()", err) panic(err) } @@ -185,6 +195,7 @@ func MustButton(image *gtk.Image, clicked func()) *gtk.Button { func MustButtonText(label string, clicked func()) *gtk.Button { button, err := gtk.ButtonNewWithLabel(label) if err != nil { + LogError("PANIC!!! - MustButtonText()", "gtk.ButtonNewWithLabel()", err) panic(err) } @@ -207,13 +218,14 @@ func MustImageFromFileWithSize(imageFileName string, width, height int) *gtk.Ima //debug.PrintStack() need to import "runtime/debug" } - p, err := gdk.PixbufNewFromFileAtScale(imageFilePath, width, height, true) + pixbuf, err := gdk.PixbufNewFromFileAtScale(imageFilePath, width, height, true) if err != nil { LogError("gtk.MustImageFromFileWithSize()", "PixbufNewFromFileAtScale()", err) } - image, err := gtk.ImageNewFromPixbuf(p) + image, err := gtk.ImageNewFromPixbuf(pixbuf) if err != nil { + LogError("PANIC!!! - MustImageFromFileWithSize()", "gtk.ImageNewFromPixbuf()", err) panic(err) } @@ -235,6 +247,7 @@ func MustImageFromFile(imageFileName string) *gtk.Image { image, err := gtk.ImageNewFromFile(imageFilePath) if err != nil { + LogError("PANIC!!! - MustImageFromFile()", "gtk.ImageNewFromFile()", err) panic(err) } @@ -283,16 +296,18 @@ func ImageFromUrl(imageUrl string) (*gtk.Image, error) { // MustCSSProviderFromFile returns a new gtk.CssProvider for a given css file, if error panics. func MustCSSProviderFromFile(css string) *gtk.CssProvider { - p, err := gtk.CssProviderNew() + cssProvider, err := gtk.CssProviderNew() if err != nil { + LogError("PANIC!!! - MustCSSProviderFromFile()", "gtk.CssProviderNew()", err) panic(err) } - if err := p.LoadFromPath(filepath.Join(StylePath, css)); err != nil { + if err := cssProvider.LoadFromPath(filepath.Join(StylePath, css)); err != nil { + LogError("PANIC!!! - MustCSSProviderFromFile()", "cssProvider.LoadFromPath()", err) panic(err) } - return p + return cssProvider } func imagePath(imageFileName string) string { @@ -301,10 +316,11 @@ func imagePath(imageFileName string) string { // MustOverlay returns a new gtk.Overlay, if error panics. func MustOverlay() *gtk.Overlay { - o, err := gtk.OverlayNew() + overlay, err := gtk.OverlayNew() if err != nil { + LogError("PANIC!!! - MustOverlay()", "gtk.OverlayNew()", err) panic(err) } - return o + return overlay } From 569907e5d939734fbfdb4626006985d2ac32dded Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Wed, 17 Feb 2021 18:08:30 -0800 Subject: [PATCH 44/94] added StructToJson() --- utils/string_utils.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/utils/string_utils.go b/utils/string_utils.go index 668f92bc..f2911a0d 100755 --- a/utils/string_utils.go +++ b/utils/string_utils.go @@ -1,6 +1,7 @@ package utils import ( + "encoding/json" "fmt" "strings" ) @@ -73,3 +74,14 @@ func TruncateString(str string, maxLength int) string { return truncateString } + + +func StructToJson(obj interface{}) (string, error) { + bytes, err := json.Marshal(obj) + if err != nil { + return "", err + } else { + jsonStr := string(bytes) + return jsonStr, nil + } +} From 7cb9d0f6313b5299924bbbe50641b83510a48c57 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 20 Feb 2021 14:45:08 -0800 Subject: [PATCH 45/94] added aditional logging to API calls --- main.go | 15 ++++++++++--- octoprintApis/ConnectRequest.go | 23 ++++++++++++++----- octoprintApis/ConnectionRequest.go | 18 ++++++++++----- octoprintApis/DisconnectRequest.go | 29 +++++++++++++++++++----- octoprintApis/FakesAckRequest.go | 28 ++++++++++++++++++----- octoprintApis/client.go | 35 +++++++++++++++++++++++++++-- octoprintApis/debugUtils.go | 36 ++++++++++++++++++++++++++++++ ui/ui.go | 6 ++--- 8 files changed, 159 insertions(+), 31 deletions(-) create mode 100755 octoprintApis/debugUtils.go diff --git a/main.go b/main.go index bc3d7cb4..d33a25da 100755 --- a/main.go +++ b/main.go @@ -10,14 +10,14 @@ import ( "strconv" "strings" + "github.com/gotk3/gotk3/gtk" + "github.com/sirupsen/logrus" "github.com/Z-Bolt/OctoScreen/ui" "github.com/Z-Bolt/OctoScreen/utils" - "github.com/gotk3/gotk3/gtk" "gopkg.in/yaml.v1" - - "github.com/sirupsen/logrus" ) + var ( BaseURL string APIKey string @@ -80,6 +80,15 @@ func init() { func setLogLevel() { logLevel := utils.LowerCaseLogLevel() + + switch logLevel { + case "debug": + octoprintApis.EnableApiLogging = true + + default: + octoprintApis.EnableApiLogging = false + } + switch logLevel { case "debug": utils.SetLogLevel(logrus.DebugLevel) diff --git a/octoprintApis/ConnectRequest.go b/octoprintApis/ConnectRequest.go index a74ded5d..9b2f5a2f 100755 --- a/octoprintApis/ConnectRequest.go +++ b/octoprintApis/ConnectRequest.go @@ -35,22 +35,33 @@ type ConnectRequest struct { } // Do sends an API request and returns an error if any. -func (cmd *ConnectRequest) Do(c *Client) error { - b := bytes.NewBuffer(nil) - if err := cmd.encode(b); err != nil { +func (cmd *ConnectRequest) Do(client *Client) error { + LogMessage("entering ConnectRequest.Do()") + + bytes := bytes.NewBuffer(nil) + if err := cmd.encode(bytes); err != nil { + LogError(err, "ConnectRequest.go, cmd.encode() failed") + LogMessage("leaving ConnectRequest.Do()") return err } - _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) + if err != nil { + LogError(err, "ConnectRequest.go, client.doJsonRequest(POST) failed") + } + + LogMessage("leaving ConnectRequest.Do()") return err } func (cmd *ConnectRequest) encode(w io.Writer) error { - return json.NewEncoder(w).Encode(struct { + payload := struct { Command string `json:"command"` ConnectRequest }{ Command: "connect", ConnectRequest: *cmd, - }) + } + + return json.NewEncoder(w).Encode(payload) } diff --git a/octoprintApis/ConnectionRequest.go b/octoprintApis/ConnectionRequest.go index a4a051ee..685e94e1 100755 --- a/octoprintApis/ConnectionRequest.go +++ b/octoprintApis/ConnectionRequest.go @@ -15,16 +15,24 @@ import ( type ConnectionRequest struct{} // Do sends an API request and returns the API response. -func (cmd *ConnectionRequest) Do(c *Client) (*dataModels.ConnectionResponse, error) { - b, err := c.doJsonRequest("GET", ConnectionApiUri, nil, nil) +func (cmd *ConnectionRequest) Do(client *Client) (*dataModels.ConnectionResponse, error) { + LogMessage("entering ConnectionRequest.Do()") + + bytes, err := client.doJsonRequest("GET", ConnectionApiUri, nil, nil) if err != nil { + LogError(err, "ConnectionRequest.go, client.doJsonRequest(GET) failed") + LogMessage("leaving ConnectionRequest.Do()") return nil, err } - r := &dataModels.ConnectionResponse{} - if err := json.Unmarshal(b, r); err != nil { + response := &dataModels.ConnectionResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + LogError(err, "ConnectionRequest.go, json.Unmarshal() failed") + LogMessage("leaving ConnectionRequest.Do()") return nil, err } - return r, err + LogMessage("leaving ConnectionRequest.Do()") + + return response, err } diff --git a/octoprintApis/DisconnectRequest.go b/octoprintApis/DisconnectRequest.go index 416c6679..ce30e84a 100755 --- a/octoprintApis/DisconnectRequest.go +++ b/octoprintApis/DisconnectRequest.go @@ -3,24 +3,41 @@ package octoprintApis import ( "bytes" "encoding/json" - // "io" + "io" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) +// TODO: DisconnectRequest doesn't seem to be used anywhere... maybe remove it? + // DisconnectRequest instructs OctoPrint to disconnect from the printer. type DisconnectRequest struct{} // Do sends an API request and returns an error if any. -func (cmd *DisconnectRequest) Do(c *Client) error { - payload := map[string]string{"command": "disconnect"} +func (cmd *DisconnectRequest) Do(client *Client) error { + LogMessage("entering DisconnectRequest.Do()") - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(payload); err != nil { + bytes := bytes.NewBuffer(nil) + if err := cmd.encode(bytes); err != nil { + LogError(err, "DisconnectRequest.go, cmd.encode() failed") + LogMessage("leaving DisconnectRequest.Do()") return err } - _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) + if err != nil { + LogError(err, "DisconnectRequest.go, client.doJsonRequest(POST) failed") + } + + LogMessage("leaving DisconnectRequest.Do()") return err } + +func (cmd *DisconnectRequest) encode(w io.Writer) error { + payload := map[string]string { + "command": "disconnect", + } + + return json.NewEncoder(w).Encode(payload) +} diff --git a/octoprintApis/FakesAckRequest.go b/octoprintApis/FakesAckRequest.go index 3b937685..8163464f 100755 --- a/octoprintApis/FakesAckRequest.go +++ b/octoprintApis/FakesAckRequest.go @@ -3,11 +3,12 @@ package octoprintApis import ( "bytes" "encoding/json" - // "io" + "io" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) +// TODO: FakesAckRequest doesn't seem to be used anywhere... maybe remove it? // FakesAckRequest fakes an acknowledgment message for OctoPrint in case one got // lost on the serial line and the communication with the printer since stalled. @@ -18,14 +19,29 @@ import ( type FakesAckRequest struct{} // Do sends an API request and returns an error if any. -func (cmd *FakesAckRequest) Do(c *Client) error { - payload := map[string]string{"command": "fake_ack"} +func (cmd *FakesAckRequest) Do(client *Client) error { + LogMessage("entering FakesAckRequest.Do()") - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(payload); err != nil { + bytes := bytes.NewBuffer(nil) + if err := cmd.encode(bytes); err != nil { + LogError(err, "FakesAckRequest.go, cmd.encode() failed") + LogMessage("leaving FakesAckRequest.Do()") return err } - _, err := c.doJsonRequest("POST", ConnectionApiUri, b, ConnectionErrors) + _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) + if err != nil { + LogError(err, "FakesAckRequest.go, client.doJsonRequest(POST) failed") + } + + LogMessage("leaving FakesAckRequest.Do()") return err } + +func (cmd *FakesAckRequest) encode(w io.Writer) error { + payload := map[string]string { + "command": "fake_ack", + } + + return json.NewEncoder(w).Encode(payload) +} diff --git a/octoprintApis/client.go b/octoprintApis/client.go index e3722dc8..c3bac81e 100755 --- a/octoprintApis/client.go +++ b/octoprintApis/client.go @@ -53,7 +53,21 @@ func (this *Client) doJsonRequest( body io.Reader, statusMapping StatusMapping, ) ([]byte, error) { - return this.doRequest(method, target, "application/json", body, statusMapping) + LogMessagef(" entering Client.doJsonRequest()") + + bytes, err := this.doRequest(method, target, "application/json", body, statusMapping) + if err != nil { + LogError(err, "Client.doJsonRequest(), this.doRequest() failed") + LogMessagef(" leaving Client.doJsonRequest()") + return nil, err + } + + // Use the following for debugging. Comment out for production. + json := string(bytes) + LogMessagef(" JSON response: %s", json) + LogMessagef(" leaving Client.doJsonRequest()") + + return bytes, err } func (this *Client) doRequest( @@ -63,8 +77,15 @@ func (this *Client) doRequest( body io.Reader, statusMapping StatusMapping, ) ([]byte, error) { + LogMessagef(" entering Client.doRequest()") + LogMessagef(" method: %s", method) + LogMessagef(" target: %s",target) + + req, err := http.NewRequest(method, joinUrl(this.Endpoint, target), body) if err != nil { + LogError(err, "Client.doRequest(), http.NewRequest() failed") + LogMessagef(" leaving Client.doRequest()") return nil, err } @@ -78,10 +99,20 @@ func (this *Client) doRequest( req.Header.Add("X-Api-Key", this.APIKey) resp, err := this.httpClient.Do(req) if err != nil { + LogError(err, "Client.doRequest(), this.httpClient.Do() failed") + LogMessagef(" leaving Client.doRequest()") + return nil, err + } + + response, err := this.handleResponse(resp, statusMapping) + if err != nil { + LogError(err, "Client.doRequest(), this.handleResponse() failed") + LogMessagef(" leaving Client.doRequest()") return nil, err } - return this.handleResponse(resp, statusMapping) + LogMessagef(" leaving Client.doRequest()") + return response, err } func (this *Client) handleResponse( diff --git a/octoprintApis/debugUtils.go b/octoprintApis/debugUtils.go new file mode 100755 index 00000000..aa353ffb --- /dev/null +++ b/octoprintApis/debugUtils.go @@ -0,0 +1,36 @@ +package octoprintApis + +import ( + "log" +) + + + +var EnableApiLogging = false + + +func LogError(err error, msg string) { + if EnableApiLogging { + log.Printf("ERROR!!! %s", err.Error()) + log.Printf("Message: %s", msg) + } +} + + +func LogMessage(v ...interface{}) { + if EnableApiLogging { + log.Print(v...) + } +} + +func LogMessagef(format string, v ...interface{}) { + if EnableApiLogging { + log.Printf(format, v...) + } +} + +func LogMessageln(v ...interface{}) { + if EnableApiLogging { + log.Println(v...) + } +} diff --git a/ui/ui.go b/ui/ui.go index 41c62bb3..e64aa782 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -53,7 +53,7 @@ func New(endpoint, key string, width, height int) *UI { height = utils.WindowHeight } - instance := &UI{ + instance := &UI { PanelHistory: stack.New(), Client: octoprintApis.NewClient(endpoint, key), NotificationsBox: uiWidgets.NewNotificationsBox(), @@ -116,6 +116,7 @@ func (this *UI) initialize() { this.window.Connect("show", this.backgroundTask.Start) this.window.Connect("destroy", func() { + utils.Logger.Debug("window destroy callback was called, now executing MainQuit()") gtk.MainQuit() }) @@ -176,6 +177,7 @@ func (this *UI) verifyConnection() { fallthrough case connectionResponse.Current.State.IsOffline(): newUIState = "splash" + utils.Logger.Info("ui.verifyConnection() - new UI state is 'splash' and is about to call ConnectRequest.Do()") if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { utils.LogError("ui.verifyConnection()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) splashMessage = "Loading..." @@ -413,8 +415,6 @@ func (this *UI) sdNotify(state string) { _, err := daemon.SdNotify(false, state) if err != nil { utils.Logger.Errorf("ui.sdNotify()", "SdNotify()", err) - utils.Logger.Debug("leaving ui.sdNotify()") - return } utils.Logger.Debug("leaving ui.sdNotify()") From c31fbb49f84e0810c8f237b74f015ecd9627b1d6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 20 Feb 2021 14:45:36 -0800 Subject: [PATCH 46/94] added HttpRequestTestWindow.go --- ui/HttpRequestTestWindow.go | 151 ++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100755 ui/HttpRequestTestWindow.go diff --git a/ui/HttpRequestTestWindow.go b/ui/HttpRequestTestWindow.go new file mode 100755 index 00000000..3033fbcb --- /dev/null +++ b/ui/HttpRequestTestWindow.go @@ -0,0 +1,151 @@ +package ui + +import ( + "fmt" + // "io/ioutil" + // standardLog "log" + // "os" + // "os/user" + // "path/filepath" + // "strconv" + // "strings" + "time" + + "github.com/coreos/go-systemd/daemon" + "github.com/gotk3/gotk3/gtk" + // "github.com/sirupsen/logrus" + // "github.com/Z-Bolt/OctoScreen/ui" + "github.com/Z-Bolt/OctoScreen/octoprintApis" + "github.com/Z-Bolt/OctoScreen/utils" + // "gopkg.in/yaml.v1" +) + + +type HttpRequestTestWindow struct { + Window *gtk.Window + Label *gtk.Label + Client *octoprintApis.Client + BackgroundTask *utils.BackgroundTask + UpdateCount int +} + + +func CreateHttpRequestTestWindow( + endpoint string, + key string, + width int, + height int, +) *HttpRequestTestWindow { + utils.Logger.Debug("entering CreateHttpRequestTestWindow()") + + + instance := &HttpRequestTestWindow { + Window: nil, + Label: nil, + Client: octoprintApis.NewClient(endpoint, key), + BackgroundTask: nil, + UpdateCount: 0, + } + + instance.BackgroundTask = utils.CreateBackgroundTask(time.Second * 10, instance.updateTestWindow) + + instance.createWindow(width, height) + instance.addControls() + defer instance.Window.ShowAll() + + + instance.sdNotify("READY=1") + //instance.sdNotify(daemon.SdNotifyReady) + + + utils.Logger.Debug("leaving CreateHttpRequestTestWindow()") + + return instance +} + + +func (this *HttpRequestTestWindow) createWindow( + width int, + height int, +) { + window, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) + if err != nil { + utils.LogFatalError("createWindow()", "WindowNew()", err) + } + + this.Window = window + this.Window.SetTitle("HTTP Request Test") + this.Window.SetDefaultSize(width, height) + + + this.Window.Connect("show", this.BackgroundTask.Start) + + this.Window.Connect("destroy", func() { + utils.Logger.Debug("destroy() callback was called") + gtk.MainQuit() + }) +} + + +func (this *HttpRequestTestWindow) addControls() { + // Create a new label widget to show in the window. + label, err := gtk.LabelNew("") + if err != nil { + utils.LogFatalError("CreateHttpRequestTestWindow()", "LabelNew()", err) + } + + this.Label = label + this.Label.SetHAlign(gtk.ALIGN_START) + this.Label.SetVAlign(gtk.ALIGN_START) + this.Window.Add(this.Label) +} + + +func (this *HttpRequestTestWindow) updateTestWindow() { + utils.Logger.Debug("entering updateTestWindow()") + + + this.UpdateCount++ + strUpdateCount := fmt.Sprintf("UpdateCount: %d", this.UpdateCount) + utils.Logger.Debug(strUpdateCount) + this.Label.SetLabel(strUpdateCount) + + + //this.checkNotification() + this.verifyConnection() + + utils.Logger.Debug("leaving updateTestWindow()") +} + + +func (this *HttpRequestTestWindow) verifyConnection() { + utils.Logger.Debug("entering verifyConnection()") + + this.sdNotify("WATCHDOG=1") + //this.sdNotify(daemon.SdNotifyWatchdog) + + connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) + if err != nil { + utils.LogError("verifyConnection()", "ConnectionRequest.Do()", err) + } else { + strCurrentState := string(connectionResponse.Current.State) + utils.Logger.Debugf(" verifyConnection() succeeded") + utils.Logger.Debugf(" connectionResponse.Current.State is %q", strCurrentState) + } + + utils.Logger.Debug("leaving verifyConnection()") +} + + +func (this *HttpRequestTestWindow) sdNotify(state string) { + utils.Logger.Debug("entering sdNotify()") + + _, err := daemon.SdNotify(false, state) + if err != nil { + utils.Logger.Errorf("sdNotify()", "SdNotify()", err) + utils.Logger.Debug("leaving sdNotify()") + return + } + + utils.Logger.Debug("leaving sdNotify()") +} From 508a34b42864b0e6f51fe305612dd4df6c32b1ed Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 20 Feb 2021 17:13:04 -0800 Subject: [PATCH 47/94] added import --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index d33a25da..3b8102fa 100755 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/sirupsen/logrus" + "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/ui" "github.com/Z-Bolt/OctoScreen/utils" "gopkg.in/yaml.v1" From e85c06a137fc7d5b2b0c9c3c034f6e45c3ea5bd7 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 21 Feb 2021 10:47:44 -0800 Subject: [PATCH 48/94] broke verifyConnection() up, added getUiStateAndMessageFromConnectionResponse() and getUiStateAndMessageFromError(), fixed bug where uninitialized was getting through --- ui/ui.go | 176 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 74 deletions(-) diff --git a/ui/ui.go b/ui/ui.go index e64aa782..3757d46e 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -60,6 +60,8 @@ func New(endpoint, key string, width, height int) *UI { OctoPrintPluginIsAvailable: true, Settings: nil, + UIState: "__uninitialized__", + window: utils.MustWindow(gtk.WINDOW_TOPLEVEL), time: time.Now(), @@ -162,112 +164,138 @@ func (this *UI) verifyConnection() { connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) if err == nil { this.ConnectionState = connectionResponse.Current.State - strCurrentState := string(connectionResponse.Current.State) - - switch { - case connectionResponse.Current.State.IsOperational(): - newUIState = "idle" - splashMessage = "Initializing..." - - case connectionResponse.Current.State.IsPrinting(): - newUIState = "printing" - splashMessage = "Printing..." - - case connectionResponse.Current.State.IsError(): - fallthrough - case connectionResponse.Current.State.IsOffline(): - newUIState = "splash" - utils.Logger.Info("ui.verifyConnection() - new UI state is 'splash' and is about to call ConnectRequest.Do()") - if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { - utils.LogError("ui.verifyConnection()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) - splashMessage = "Loading..." - } else { - // Use 'Offline.' here and 'offline!' later. Having different variations may help in - // troubleshooting any issues around this state. - splashMessage = "Printer is Offline." - } - - case connectionResponse.Current.State.IsConnecting(): - newUIState = "splash" - splashMessage = strCurrentState - - default: - switch strCurrentState { - case "Cancelling": - newUIState = "idle" - - default: - logLevel := utils.LowerCaseLogLevel() - if logLevel == "debug" { - utils.Logger.Fatalf("menu.getPanel() - unknown CurrentState: %q", strCurrentState) - } - } - } + newUIState, splashMessage = this.getUiStateAndMessageFromConnectionResponse(connectionResponse, newUIState, splashMessage) } else { utils.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err) - utils.Logger.Info("ui.verifyConnection() - now setting newUIState to 'splash'") - newUIState = "splash" + newUIState, splashMessage = this.getUiStateAndMessageFromErrorResponse(err, newUIState, splashMessage) + } - if time.Since(this.time) > errMercyPeriod { - errMessage := this.errToUser(err) + this.splashPanel.Label.SetText(splashMessage) - utils.Logger.Info("ui.verifyConnection() - printer is offline") - utils.Logger.Infof("ui.verifyConnection() - errMessage is: %q", errMessage) + defer func() { + this.setUiState(newUIState, splashMessage) + }() + + utils.Logger.Debug("leaving ui.verifyConnection()") +} - if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") { - utils.Logger.Errorf("ui.verifyConnection() - %s", errMessage) - splashMessage = "Printer is offline (deadline exceeded)" - } else if strings.Contains(strings.ToLower(errMessage), "connection reset by peer") { - utils.Logger.Errorf("ui.verifyConnection() - %s", errMessage) - splashMessage = "Printer is offline (peer connection reset)" + +func (this *UI) getUiStateAndMessageFromConnectionResponse( + connectionResponse *dataModels.ConnectionResponse, + newUIState string, + splashMessage string, +) (string, string) { + strCurrentState := string(connectionResponse.Current.State) + + switch { + case connectionResponse.Current.State.IsOperational(): + newUIState = "idle" + splashMessage = "Initializing..." + + case connectionResponse.Current.State.IsPrinting(): + newUIState = "printing" + splashMessage = "Printing..." + + case connectionResponse.Current.State.IsError(): + fallthrough + case connectionResponse.Current.State.IsOffline(): + newUIState = "splash" + utils.Logger.Info("ui.getUiStateAndMessageFromConnectionResponse() - new UI state is 'splash' and is about to call ConnectRequest.Do()") + if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { + utils.LogError("ui.getUiStateAndMessageFromConnectionResponse()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) + splashMessage = "Loading..." } else { - splashMessage = errMessage + splashMessage = "Printer is offline, now trying to connect..." + } + + case connectionResponse.Current.State.IsConnecting(): + newUIState = "splash" + splashMessage = strCurrentState + + default: + switch strCurrentState { + case "Cancelling": + newUIState = "idle" + + default: + utils.Logger.Errorf("ui.getUiStateAndMessageFromConnectionResponse() - unknown CurrentState: %q", strCurrentState) } + } + + return newUIState, splashMessage +} + + +func (this *UI) getUiStateAndMessageFromErrorResponse( + err error, + newUIState string, + splashMessage string, +) (string, string) { + utils.Logger.Info("ui.getUiStateAndMessageFromErrorResponse() - now setting newUIState to 'splash'") + newUIState = "splash" + + if time.Since(this.time) > errMercyPeriod { + errMessage := this.errToUser(err) + + utils.Logger.Info("ui.getUiStateAndMessageFromErrorResponse() - printer is offline") + utils.Logger.Infof("ui.getUiStateAndMessageFromErrorResponse() - errMessage is: %q", errMessage) + + if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") { + splashMessage = "Printer is offline (deadline exceeded), retrying to connect..." + } else if strings.Contains(strings.ToLower(errMessage), "connection reset by peer") { + splashMessage = "Printer is offline (peer connection reset), retrying to connect..." + } else if strings.Contains(strings.ToLower(errMessage), "unexpected status code: 403") { + splashMessage = "Printer is offline (403), retrying to connect..." } else { - // Use 'offline!' here and 'OFFLINE' above. Having different variations may help in - // troubleshooting any issues around this state. - splashMessage = "Printer is offline!" + splashMessage = errMessage } + } else { + splashMessage = "Printer is offline! (retrying to connect...)" } - defer func() { - this.UIState = newUIState - }() + return newUIState, splashMessage +} + + +func (this *UI) setUiState( + newUiState string, + splashMessage string, +) { + utils.Logger.Debug("entering ui.setUiState()") this.splashPanel.Label.SetText(splashMessage) - if newUIState == this.UIState { - utils.Logger.Infof("ui.verifyConnection() - newUIState equals ui.UIState and is: %q", this.UIState) - utils.Logger.Debug("leaving ui.verifyConnection()") + if newUiState == this.UIState { + utils.Logger.Infof("ui.setUiState() - newUiState and ui.UIState are the same (%q)", this.UIState) + utils.Logger.Debug("leaving ui.setUiState()") return } - utils.Logger.Info("ui.verifyConnection() - newUIState does not equals ui.UIState") - utils.Logger.Infof("ui.verifyConnection() - ui.UIState is: %q", this.UIState) - utils.Logger.Infof("ui.verifyConnection() - newUIState is: %q", newUIState) + utils.Logger.Info("ui.setUiState() - newUiState does not equal ui.UIState") + utils.Logger.Infof("ui.setUiState() - ui.UIState is: %q", this.UIState) + utils.Logger.Infof("ui.setUiState() - newUiState is: %q", newUiState) + this.UIState = newUiState - switch newUIState { + switch newUiState { case "idle": - utils.Logger.Info("ui.verifyConnection() - printer is ready") + utils.Logger.Info("ui.setUiState() - printer is ready") this.GoToPanel(IdleStatusPanel(this)) case "printing": - utils.Logger.Info("ui.verifyConnection() - printing a job") + utils.Logger.Info("ui.setUiState() - printing a job") this.GoToPanel(PrintStatusPanel(this)) case "splash": this.GoToPanel(this.splashPanel) default: - logLevel := utils.LowerCaseLogLevel() - if logLevel == "debug" { - utils.Logger.Fatalf("ui.verifyConnection() - unknown switch of newUIState: %q", newUIState) - } + utils.Logger.Errorf("ERROR: ui.setUiState() - unknown newUiState case: %q", newUiState) } - utils.Logger.Debug("leaving ui.verifyConnection()") + utils.Logger.Debug("leaving ui.setUiState()") } + func (this *UI) checkNotification() { utils.Logger.Debug("entering ui.checkNotification()") From 2cacaf4e12242cafec6dd8a0738368a6d48a13fc Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 21 Feb 2021 10:47:49 -0800 Subject: [PATCH 49/94] broke verifyConnection() up, added getUiStateAndMessageFromConnectionResponse() and getUiStateAndMessageFromError(), fixed bug where uninitialized was getting through --- ui/ui.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/ui.go b/ui/ui.go index 3757d46e..021f205c 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -167,7 +167,7 @@ func (this *UI) verifyConnection() { newUIState, splashMessage = this.getUiStateAndMessageFromConnectionResponse(connectionResponse, newUIState, splashMessage) } else { utils.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err) - newUIState, splashMessage = this.getUiStateAndMessageFromErrorResponse(err, newUIState, splashMessage) + newUIState, splashMessage = this.getUiStateAndMessageFromError(err, newUIState, splashMessage) } this.splashPanel.Label.SetText(splashMessage) @@ -226,19 +226,19 @@ func (this *UI) getUiStateAndMessageFromConnectionResponse( } -func (this *UI) getUiStateAndMessageFromErrorResponse( +func (this *UI) getUiStateAndMessageFromError( err error, newUIState string, splashMessage string, ) (string, string) { - utils.Logger.Info("ui.getUiStateAndMessageFromErrorResponse() - now setting newUIState to 'splash'") + utils.Logger.Info("ui.getUiStateAndMessageFromError() - now setting newUIState to 'splash'") newUIState = "splash" if time.Since(this.time) > errMercyPeriod { errMessage := this.errToUser(err) - utils.Logger.Info("ui.getUiStateAndMessageFromErrorResponse() - printer is offline") - utils.Logger.Infof("ui.getUiStateAndMessageFromErrorResponse() - errMessage is: %q", errMessage) + utils.Logger.Info("ui.getUiStateAndMessageFromError() - printer is offline") + utils.Logger.Infof("ui.getUiStateAndMessageFromError() - errMessage is: %q", errMessage) if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") { splashMessage = "Printer is offline (deadline exceeded), retrying to connect..." From 2c3d5e04c3a48e05cf6c7266318004a02ec61b3f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 21 Feb 2021 10:49:30 -0800 Subject: [PATCH 50/94] added comment about how updateTemperaturesCallback() needs to guard when not connected, but can't do this at the moment due to circular dependency --- utils/UpdateTemperaturesBackgroundTask.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/UpdateTemperaturesBackgroundTask.go b/utils/UpdateTemperaturesBackgroundTask.go index 4915ced5..43890645 100755 --- a/utils/UpdateTemperaturesBackgroundTask.go +++ b/utils/UpdateTemperaturesBackgroundTask.go @@ -15,7 +15,10 @@ var UpdateTemperaturesBackgroundTask *BackgroundTask = nil var temperatureDataDisplays []interfaces.ITemperatureDataDisplay var registeredClient *octoprintApis.Client = nil -func CreateUpdateTemperaturesBackgroundTask(temperatureDataDisplay interfaces.ITemperatureDataDisplay, client *octoprintApis.Client) { +func CreateUpdateTemperaturesBackgroundTask( + temperatureDataDisplay interfaces.ITemperatureDataDisplay, + client *octoprintApis.Client, +) { if UpdateTemperaturesBackgroundTask != nil { Logger.Error("UpdateTemperaturesBackgroundTask.CreateUpdateTemperaturesBackgroundTask() - updateTemperaturesBackgroundTask has already been set") return @@ -32,6 +35,14 @@ func RegisterTemperatureStatusBox(temperatureDataDisplay interfaces.ITemperature } func updateTemperaturesCallback() { + + // TODO: add guard if printer isn't connected + // can't do right now due to circular dependency: + // TemperatureStatusBox creates the background task... + // background task needs UI.UIState or UIState.connectionAttempts + // UI has panel + // panel has TemperatureStatusBox + currentTemperatureData, err := GetCurrentTemperatureData(registeredClient) if err != nil { LogError("UpdateTemperaturesBackgroundTask.updateTemperaturesCallback()", "GetCurrentTemperatureData(client)", err) From 55960bb55fe5dd6fb699d0ab86720cfed09da120 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 21 Feb 2021 10:50:47 -0800 Subject: [PATCH 51/94] added MISSING_ENV_TOKEN and INVALID_ENV_TOKEN --- utils/environment.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/utils/environment.go b/utils/environment.go index 9e87a1a5..2dc07f0b 100755 --- a/utils/environment.go +++ b/utils/environment.go @@ -6,6 +6,10 @@ import ( //"strings" ) + +const MISSING_ENV_TOKEN = ">>MISSING<<" +const INVALID_ENV_TOKEN = "!!!INVALID!!!" + // Required environment variables const ( EnvStylePath = "OCTOSCREEN_STYLE_PATH" @@ -115,7 +119,7 @@ func DumpEnvironmentVariables() { func dumpEnvironmentVariable(key string) { value := os.Getenv(key) if value == "" { - value = ">>MISSING<<" + value = MISSING_ENV_TOKEN } Logger.Infof("key: %q, value: %q", key, value) @@ -124,7 +128,7 @@ func dumpEnvironmentVariable(key string) { func dumpObfuscatedEnvironmentVariable(key string) { value := os.Getenv(key) if value == "" { - value = ">>MISSING<<" + value = MISSING_ENV_TOKEN } else { value = GetObfuscatedValue(value) } @@ -137,16 +141,20 @@ func GetObfuscatedValue(value string) string { obfuscatedValue := "" if length < 6 { - obfuscatedValue = "!!!INVALID!!!" + obfuscatedValue = INVALID_ENV_TOKEN } else { - obfuscatedValue = fmt.Sprintf("%c%c%c---%c%c%c", - value[0], - value[1], - value[2], - value[length - 3], - value[length - 2], - value[length - 1], - ) + if value == MISSING_ENV_TOKEN { + return value + } else { + obfuscatedValue = fmt.Sprintf("%c%c%c---%c%c%c", + value[0], + value[1], + value[2], + value[length - 3], + value[length - 2], + value[length - 1], + ) + } } return obfuscatedValue From 0242f95113663edf58b49589d3c47aba425ebe07 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 21 Feb 2021 11:35:01 -0800 Subject: [PATCH 52/94] added more logging to ui.go --- ui/ui.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ui/ui.go b/ui/ui.go index 021f205c..4a3bac6b 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -163,6 +163,14 @@ func (this *UI) verifyConnection() { connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) if err == nil { + utils.Logger.Debug("ui.verifyConnection() - ConnectionRequest.Do() succeeded") + jsonResponse, err := utils.StructToJson(connectionResponse) + if err != nil { + utils.Logger.Debug("ui.verifyConnection() - utils.StructToJson() failed") + } else { + utils.Logger.Debug("ui.verifyConnection() - connectionResponse is: %s", jsonResponse) + } + this.ConnectionState = connectionResponse.Current.State newUIState, splashMessage = this.getUiStateAndMessageFromConnectionResponse(connectionResponse, newUIState, splashMessage) } else { @@ -185,20 +193,27 @@ func (this *UI) getUiStateAndMessageFromConnectionResponse( newUIState string, splashMessage string, ) (string, string) { + utils.Logger.Debug("entering ui.getUiStateAndMessageFromConnectionResponse()") + strCurrentState := string(connectionResponse.Current.State) + utils.Logger.Debugf("ui.getUiStateAndMessageFromConnectionResponse() - strCurrentState is %s", strCurrentState) switch { case connectionResponse.Current.State.IsOperational(): + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is idle") newUIState = "idle" splashMessage = "Initializing..." case connectionResponse.Current.State.IsPrinting(): + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is printing") newUIState = "printing" splashMessage = "Printing..." case connectionResponse.Current.State.IsError(): + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state has an error") fallthrough case connectionResponse.Current.State.IsOffline(): + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state is now offline and displaying the splash panel") newUIState = "splash" utils.Logger.Info("ui.getUiStateAndMessageFromConnectionResponse() - new UI state is 'splash' and is about to call ConnectRequest.Do()") if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { @@ -209,10 +224,12 @@ func (this *UI) getUiStateAndMessageFromConnectionResponse( } case connectionResponse.Current.State.IsConnecting(): + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is splash (from IsConnecting)") newUIState = "splash" splashMessage = strCurrentState default: + utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the default case was hit") switch strCurrentState { case "Cancelling": newUIState = "idle" @@ -222,6 +239,8 @@ func (this *UI) getUiStateAndMessageFromConnectionResponse( } } + utils.Logger.Debug("leaving ui.getUiStateAndMessageFromConnectionResponse()") + return newUIState, splashMessage } @@ -231,6 +250,8 @@ func (this *UI) getUiStateAndMessageFromError( newUIState string, splashMessage string, ) (string, string) { + utils.Logger.Debug("entering ui.getUiStateAndMessageFromError()") + utils.Logger.Info("ui.getUiStateAndMessageFromError() - now setting newUIState to 'splash'") newUIState = "splash" @@ -253,6 +274,8 @@ func (this *UI) getUiStateAndMessageFromError( splashMessage = "Printer is offline! (retrying to connect...)" } + utils.Logger.Debug("leaving ui.getUiStateAndMessageFromError()") + return newUIState, splashMessage } From ced239ff60186fe2160c4b67d779a2b030370f1f Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Thu, 25 Feb 2021 18:49:25 -0800 Subject: [PATCH 53/94] added call to sdNotify() to prevent crashing when printer is unplugged --- ui/ui.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/ui.go b/ui/ui.go index 4a3bac6b..4542d00e 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -168,7 +168,7 @@ func (this *UI) verifyConnection() { if err != nil { utils.Logger.Debug("ui.verifyConnection() - utils.StructToJson() failed") } else { - utils.Logger.Debug("ui.verifyConnection() - connectionResponse is: %s", jsonResponse) + utils.Logger.Debugf("ui.verifyConnection() - connectionResponse is: %s", jsonResponse) } this.ConnectionState = connectionResponse.Current.State @@ -422,6 +422,7 @@ func (this *UI) update() { if this.connectionAttempts > 8 { this.splashPanel.putOnHold() + this.sdNotify("WATCHDOG=1") utils.Logger.Debug("leaving ui.update() - connectionAttempts > 8") return From 6d9480ca11ade51b736fb82334b634a8a727bd8d Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 09:15:59 -0800 Subject: [PATCH 54/94] moved logger into it's own folder/package --- {utils => logger}/logger.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {utils => logger}/logger.go (100%) diff --git a/utils/logger.go b/logger/logger.go similarity index 100% rename from utils/logger.go rename to logger/logger.go From 5bd78c769b6aef7ab2b0d3036f9d276a530ea939 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 09:30:20 -0800 Subject: [PATCH 55/94] updated code to use new logger library --- logger/contextHook.go | 38 ++++ logger/logger.go | 172 +++++++++++------ octoprintApis/BedOffsetRequest.go | 1 - octoprintApis/BedStateRequest.go | 1 - octoprintApis/BedTargetRequest.go | 1 - octoprintApis/CancelRequest.go | 1 - octoprintApis/CommandRequest.go | 1 - octoprintApis/ConnectRequest.go | 11 +- octoprintApis/ConnectionRequest.go | 14 +- octoprintApis/CustomCommandsRequest.go | 1 - octoprintApis/DisconnectRequest.go | 15 +- octoprintApis/FakesAckRequest.go | 16 +- octoprintApis/FileRequest.go | 1 - octoprintApis/FullStateRequest.go | 1 - octoprintApis/JobRequest.go | 1 - octoprintApis/NotificationRequest.go | 1 - octoprintApis/OctoScreenSettingsRequest.go | 1 - octoprintApis/PauseRequest.go | 1 - octoprintApis/PluginManagerInfoRequest.go | 16 +- octoprintApis/PrintHeadHomeRequest.go | 1 - octoprintApis/PrintHeadJogRequest.go | 1 - octoprintApis/RestartRequest.go | 1 - octoprintApis/RunZOffsetCalibrationRequest.go | 15 +- octoprintApis/SdInitRequest.go | 1 - octoprintApis/SdRefreshRequest.go | 1 - octoprintApis/SdReleaseRequest.go | 1 - octoprintApis/SdStateRequest.go | 1 - octoprintApis/StartRequest.go | 1 - octoprintApis/StatusMapping.go | 1 - octoprintApis/TemperatureDataRequest.go | 1 - octoprintApis/ToolExtrudeRequest.go | 1 - octoprintApis/ToolFlowRateRequest.go | 1 - octoprintApis/ToolOffsetRequest.go | 1 - octoprintApis/ToolSelectRequest.go | 1 - octoprintApis/ToolStateRequest.go | 1 - octoprintApis/ToolTargetRequest.go | 1 - octoprintApis/ZOffsetRequest.go | 36 ++-- octoprintApis/client.go | 39 ++-- octoprintApis/dataModels/FileResponse.go | 1 - octoprintApis/debugUtils.go | 36 ---- octoprintApis/job.go | 1 - octoprintApis/printer.go | 1 - octoprintApis/zbolt.go | 1 - ui/BedLevelPanel.go | 23 ++- ui/ControlPanel.go | 11 +- ui/FatalErrorWindow.go | 7 +- ui/FilesPanel.go | 15 +- ui/HttpRequestTestWindow.go | 51 +++-- ui/IdleStatusPanel.go | 46 +++-- ui/NetworkPanel.go | 9 +- ui/PrintStatusPanel.go | 37 ++-- ui/SplashPanel.go | 28 +-- ui/TemperaturePresetsPanel.go | 5 +- ui/menu.go | 26 +-- ui/tool_changer_panel.go | 11 +- ui/ui.go | 181 +++++++++--------- ui/z_offset_calibration_panel.go | 19 +- uiWidgets/AmountToExtrudeStepButton.go | 4 +- uiWidgets/AmountToMoveStepButton.go | 4 +- uiWidgets/CommandButton.go | 5 +- uiWidgets/ControlButton.go | 7 +- uiWidgets/CoolDownButton.go | 7 +- uiWidgets/FanButton.go | 5 +- uiWidgets/FilamentExtrudeButton.go | 3 +- uiWidgets/FilamentLoadButton.go | 3 +- uiWidgets/FlowRateStepButton.go | 3 +- uiWidgets/HomeAllButton.go | 9 +- uiWidgets/HomeButton.go | 7 +- uiWidgets/ManualZCalibrationStepButton.go | 4 +- uiWidgets/MoveButton.go | 4 +- uiWidgets/MustPressedButton.go | 3 +- uiWidgets/OctoPrintInfoBox.go | 4 +- uiWidgets/OctoScreenPluginInfoBox.go | 3 +- uiWidgets/SelectToolStepButton.go | 5 +- uiWidgets/StepButton.go | 3 +- uiWidgets/SystemCommandButton.go | 5 +- uiWidgets/SystemInfoBox.go | 3 +- uiWidgets/SystemInformationInfoBox.go | 3 +- uiWidgets/TemperatureAmountStepButton.go | 4 +- uiWidgets/TemperatureIncreaseButton.go | 9 +- uiWidgets/TemperaturePresetButton.go | 15 +- uiWidgets/TemperatureStatusBox.go | 5 +- uiWidgets/ToolButton.go | 9 +- utils/BackgroundTask.go | 7 +- utils/LocationHistory.go | 3 +- utils/UpdateTemperaturesBackgroundTask.go | 15 +- utils/environment.go | 20 +- utils/filament.go | 15 +- utils/gtk.go | 45 ++--- utils/tools.go | 63 +++--- 90 files changed, 638 insertions(+), 575 deletions(-) create mode 100755 logger/contextHook.go delete mode 100755 octoprintApis/debugUtils.go diff --git a/logger/contextHook.go b/logger/contextHook.go new file mode 100755 index 00000000..fd867513 --- /dev/null +++ b/logger/contextHook.go @@ -0,0 +1,38 @@ +package logger + +import ( + // "io" + // "os" + "path" + "runtime" + "strings" + // "time" + + "github.com/sirupsen/logrus" +) + + +type ContextHook struct{} + +func (hook ContextHook) Levels() []logrus.Level { + return logrus.AllLevels +} + +func (hook ContextHook) Fire(entry *logrus.Entry) error { + pc := make([]uintptr, 3, 3) + cnt := runtime.Callers(6, pc) + + for i := 0; i < cnt; i++ { + fu := runtime.FuncForPC(pc[i] - 1) + name := fu.Name() + if !strings.Contains(strings.ToLower(name), "github.com/sirupsen/logrus") { + file, line := fu.FileLine(pc[i] - 1) + entry.Data["file"] = path.Base(file) + entry.Data["func"] = path.Base(name) + entry.Data["line"] = line + break + } + } + + return nil +} diff --git a/logger/logger.go b/logger/logger.go index 8dce9535..1f34cd72 100755 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,98 +1,154 @@ -package utils +package logger import ( + "fmt" "io" standardLog "log" "os" - "path" - "runtime" + // "path" + // "runtime" "strings" // "time" "github.com/sirupsen/logrus" ) -type ContextHook struct{} -func (hook ContextHook) Levels() []logrus.Level { - return logrus.AllLevels -} +var _indentLevel int +var _indentation string +const INDENTATION_TOKEN = " " +const INDENTATION_TOKEN_LENGTH = 4 -func (hook ContextHook) Fire(entry *logrus.Entry) error { - pc := make([]uintptr, 3, 3) - cnt := runtime.Callers(6, pc) - - for i := 0; i < cnt; i++ { - fu := runtime.FuncForPC(pc[i] - 1) - name := fu.Name() - if !strings.Contains(strings.ToLower(name), "github.com/sirupsen/logrus") { - file, line := fu.FileLine(pc[i] - 1) - entry.Data["file"] = path.Base(file) - entry.Data["func"] = path.Base(name) - entry.Data["line"] = line - break - } - } - return nil -} - - -var log *logrus.Logger -var Logger *logrus.Entry - -func SetLogLevel(level logrus.Level) { - log.SetLevel(level) - standardLog.Printf("logger.SetLogLevel() - the log level is now set to: %q", level) -} - -func LowerCaseLogLevel() string { - logLevel := os.Getenv(EnvLogLevel) - return strings.ToLower(logLevel) -} +var _logrusLogger *logrus.Logger +var _logrusEntry *logrus.Entry +var _logLevel logrus.Level +var _strLogLevel string func init() { - log = logrus.New() - log.AddHook(ContextHook{}) + _indentLevel = 0 + _indentation = "" - // Start off with the logging level set to debug until we get a chance to read the configuration settings. - SetLogLevel(logrus.DebugLevel) + _logrusLogger = logrus.New() + _logrusLogger.AddHook(ContextHook{}) + // + // TODO: ...(maybe?) it would be nice it this could be made generic, + // but this is getting set in init(). var logFilePath = os.Getenv("OCTOSCREEN_LOG_FILE_PATH") + // if logFilePath == "" { - log.Infof("logger.init() - logFilePath is was not defined. Now using just the standard console output.") - log.Out = os.Stdout + standardLog.Print("logger.init() - logFilePath is was not defined. Now using just the standard console output.") + _logrusLogger.Out = os.Stdout } else { - log.Infof("logger.init() - logFilePath is: %q", logFilePath) + standardLog.Printf("logger.init() - logFilePath is: %s", logFilePath) file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err == nil { - log.Infof("logger.init() - OpenFile() succeeded and now setting log.Out to %s", logFilePath) - log.Out = file + standardLog.Printf("logger.init() - OpenFile() succeeded and now setting log.Out to %s", logFilePath) + _logrusLogger.Out = file - log.Out = io.MultiWriter(os.Stdout, file) - logrus.SetOutput(log.Out) + _logrusLogger.Out = io.MultiWriter(os.Stdout, file) + logrus.SetOutput(_logrusLogger.Out) } else { - log.Errorf("logger.init() - OpenFile() FAILED! err is: %q", err) - log.Error("Failed to log to file, using default stderr") + standardLog.Printf("logger.init() - OpenFile() FAILED! err is: %s", err.Error) + standardLog.Print("Failed to open the log file, defaulting to use the standard console output.") + _logrusLogger.Out = os.Stdout } } - Logger = log.WithFields(logrus.Fields{}) + _logrusEntry = _logrusLogger.WithFields(logrus.Fields{}) + + // Start off with the logging level set to debug until we get a chance to read the configuration settings. + SetLogLevel(logrus.DebugLevel) +} + +func SetLogLevel(newLevel logrus.Level) { + _logLevel = newLevel + _strLogLevel = strings.ToLower(_logLevel.String()) + + _logrusLogger.SetLevel(_logLevel) + standardLog.Printf("logger.SetLogLevel() - the log level is now set to: %s", _strLogLevel) +} + +func LogLevel() string { + // Returns a lower case string. + return _strLogLevel +} + + +func TraceEnter(functionName string) { + message := fmt.Sprintf("%sentering %s", _indentation, functionName) + _logrusEntry.Debug(message) + _indentLevel++ + _indentation += INDENTATION_TOKEN +} + +func TraceLeave(functionName string) { + _indentLevel-- + _indentation = _indentation[:(_indentLevel * INDENTATION_TOKEN_LENGTH)] + message := fmt.Sprintf("%sleaving %s", _indentation, functionName) + _logrusEntry.Debug(message) } -func LogError(currentFunctionName, functionNameCalled string, err error) { + +func LogError(currentFunctionName, functionCalledName string, err error) { if err != nil { - Logger.Errorf("%s - %s returned an error: %q", currentFunctionName, functionNameCalled, err) + _logrusEntry.Errorf("%s%s - %s returned an error: %q", _indentation, currentFunctionName, functionCalledName, err) } else { - Logger.Errorf("%s - %s returned an error", currentFunctionName, functionNameCalled) + _logrusEntry.Errorf("%s%s - %s returned an error", _indentation, currentFunctionName, functionCalledName) } } -func LogFatalError(currentFunctionName, functionNameCalled string, err error) { +func LogFatalError(currentFunctionName, functionCalledName string, err error) { if err != nil { - Logger.Fatalf("%s - %s returned an error: %q", currentFunctionName, functionNameCalled, err) + _logrusEntry.Fatalf("%s%s - %s returned an error: %q", _indentation, currentFunctionName, functionCalledName, err) } else { - Logger.Fatalf("%s - %s returned an error", currentFunctionName, functionNameCalled) + _logrusEntry.Fatalf("%s%s - %s returned an error", _indentation, currentFunctionName, functionCalledName) } } + + +func Debug(args ...interface{}) { + _logrusEntry.Debug(_indentation + fmt.Sprint(args...)) +} + +func Debugf(format string, args ...interface{}) { + _logrusEntry.Debugf(_indentation + format, args...) +} + + +func Info(args ...interface{}) { + _logrusEntry.Info(_indentation + fmt.Sprint(args...)) +} + +func Infof(format string, args ...interface{}) { + _logrusEntry.Infof(_indentation + format, args...) +} + + +func Warn(args ...interface{}) { + _logrusEntry.Warn(_indentation + fmt.Sprint(args...)) +} + +func Warnf(format string, args ...interface{}) { + _logrusEntry.Warnf(_indentation + format, args...) +} + + +func Error(args ...interface{}) { + _logrusEntry.Error(_indentation + fmt.Sprint(args...)) +} + +func Errorf(format string, args ...interface{}) { + _logrusEntry.Errorf(_indentation + format, args...) +} + + +func Fatal(args ...interface{}) { + _logrusEntry.Fatal(_indentation + fmt.Sprint(args...)) +} + +func Fatalf(format string, args ...interface{}) { + _logrusEntry.Fatalf(_indentation + format, args...) +} diff --git a/octoprintApis/BedOffsetRequest.go b/octoprintApis/BedOffsetRequest.go index 5ec87bb7..d0fff548 100755 --- a/octoprintApis/BedOffsetRequest.go +++ b/octoprintApis/BedOffsetRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/BedStateRequest.go b/octoprintApis/BedStateRequest.go index 3b1a1abd..893e9ad9 100755 --- a/octoprintApis/BedStateRequest.go +++ b/octoprintApis/BedStateRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" // "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/BedTargetRequest.go b/octoprintApis/BedTargetRequest.go index 536bd7b7..64936ea9 100755 --- a/octoprintApis/BedTargetRequest.go +++ b/octoprintApis/BedTargetRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/CancelRequest.go b/octoprintApis/CancelRequest.go index 33c69cff..4b4ed193 100755 --- a/octoprintApis/CancelRequest.go +++ b/octoprintApis/CancelRequest.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" // "io" - // "log" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/CommandRequest.go b/octoprintApis/CommandRequest.go index f2dbaa84..758a6360 100755 --- a/octoprintApis/CommandRequest.go +++ b/octoprintApis/CommandRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" // "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ConnectRequest.go b/octoprintApis/ConnectRequest.go index 9b2f5a2f..2b7d2f2d 100755 --- a/octoprintApis/ConnectRequest.go +++ b/octoprintApis/ConnectRequest.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -36,21 +37,21 @@ type ConnectRequest struct { // Do sends an API request and returns an error if any. func (cmd *ConnectRequest) Do(client *Client) error { - LogMessage("entering ConnectRequest.Do()") + logger.TraceEnter("ConnectRequest.Do()") bytes := bytes.NewBuffer(nil) if err := cmd.encode(bytes); err != nil { - LogError(err, "ConnectRequest.go, cmd.encode() failed") - LogMessage("leaving ConnectRequest.Do()") + logger.LogError("ConnectRequest.Do()", "cmd.encode()", err) + logger.TraceLeave("ConnectRequest.Do()") return err } _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) if err != nil { - LogError(err, "ConnectRequest.go, client.doJsonRequest(POST) failed") + logger.LogError("ConnectRequest.go()", "client.doJsonRequest(POST)", err) } - LogMessage("leaving ConnectRequest.Do()") + logger.TraceLeave("ConnectRequest.Do()") return err } diff --git a/octoprintApis/ConnectionRequest.go b/octoprintApis/ConnectionRequest.go index 685e94e1..49b4e15a 100755 --- a/octoprintApis/ConnectionRequest.go +++ b/octoprintApis/ConnectionRequest.go @@ -5,6 +5,7 @@ import ( "encoding/json" // "io" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -16,23 +17,22 @@ type ConnectionRequest struct{} // Do sends an API request and returns the API response. func (cmd *ConnectionRequest) Do(client *Client) (*dataModels.ConnectionResponse, error) { - LogMessage("entering ConnectionRequest.Do()") + logger.TraceEnter("ConnectionRequest.Do()") bytes, err := client.doJsonRequest("GET", ConnectionApiUri, nil, nil) if err != nil { - LogError(err, "ConnectionRequest.go, client.doJsonRequest(GET) failed") - LogMessage("leaving ConnectionRequest.Do()") + logger.LogError("ConnectionRequest.Do()", "client.doJsonRequest(GET)", err) + logger.TraceLeave("ConnectionRequest.Do()") return nil, err } response := &dataModels.ConnectionResponse{} if err := json.Unmarshal(bytes, response); err != nil { - LogError(err, "ConnectionRequest.go, json.Unmarshal() failed") - LogMessage("leaving ConnectionRequest.Do()") + logger.LogError("ConnectionRequest.Do()", "json.Unmarshal()", err) + logger.TraceLeave("ConnectionRequest.Do()") return nil, err } - LogMessage("leaving ConnectionRequest.Do()") - + logger.TraceLeave("ConnectionRequest.Do()") return response, err } diff --git a/octoprintApis/CustomCommandsRequest.go b/octoprintApis/CustomCommandsRequest.go index 5a7e9162..485533bd 100755 --- a/octoprintApis/CustomCommandsRequest.go +++ b/octoprintApis/CustomCommandsRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" // "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/DisconnectRequest.go b/octoprintApis/DisconnectRequest.go index ce30e84a..3cdf7b6e 100755 --- a/octoprintApis/DisconnectRequest.go +++ b/octoprintApis/DisconnectRequest.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -15,22 +16,22 @@ import ( type DisconnectRequest struct{} // Do sends an API request and returns an error if any. -func (cmd *DisconnectRequest) Do(client *Client) error { - LogMessage("entering DisconnectRequest.Do()") +func (this *DisconnectRequest) Do(client *Client) error { + logger.TraceEnter("DisconnectRequest.Do()") bytes := bytes.NewBuffer(nil) - if err := cmd.encode(bytes); err != nil { - LogError(err, "DisconnectRequest.go, cmd.encode() failed") - LogMessage("leaving DisconnectRequest.Do()") + if err := this.encode(bytes); err != nil { + logger.LogError("DisconnectRequest.Do()", "this.encode(bytes)", err) + logger.TraceLeave("DisconnectRequest.Do()") return err } _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) if err != nil { - LogError(err, "DisconnectRequest.go, client.doJsonRequest(POST) failed") + logger.LogError("DisconnectRequest.Do()", "client.doJsonRequest(POST)", err) } - LogMessage("leaving DisconnectRequest.Do()") + logger.TraceLeave("DisconnectRequest.Do()") return err } diff --git a/octoprintApis/FakesAckRequest.go b/octoprintApis/FakesAckRequest.go index 8163464f..939b1aea 100755 --- a/octoprintApis/FakesAckRequest.go +++ b/octoprintApis/FakesAckRequest.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -19,22 +20,23 @@ import ( type FakesAckRequest struct{} // Do sends an API request and returns an error if any. -func (cmd *FakesAckRequest) Do(client *Client) error { - LogMessage("entering FakesAckRequest.Do()") +func (this *FakesAckRequest) Do(client *Client) error { + logger.TraceEnter("FakesAckRequest.Do()") bytes := bytes.NewBuffer(nil) - if err := cmd.encode(bytes); err != nil { - LogError(err, "FakesAckRequest.go, cmd.encode() failed") - LogMessage("leaving FakesAckRequest.Do()") + if err := this.encode(bytes); err != nil { + logger.LogError("FakesAckRequest.Do()", "this.encode(bytes)", err) + logger.TraceLeave("FakesAckRequest.Do()") return err } _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors) if err != nil { - LogError(err, "FakesAckRequest.go, client.doJsonRequest(POST) failed") + logger.LogError("FakesAckRequest.Do()", "client.doJsonRequest(POST)", err) + logger.LogError("main.findConfigFile()", "Current()", err) } - LogMessage("leaving FakesAckRequest.Do()") + logger.TraceLeave("FakesAckRequest.Do()") return err } diff --git a/octoprintApis/FileRequest.go b/octoprintApis/FileRequest.go index d337b28f..cc872b9e 100755 --- a/octoprintApis/FileRequest.go +++ b/octoprintApis/FileRequest.go @@ -4,7 +4,6 @@ package octoprintApis import ( "encoding/json" "fmt" - // "log" // "strconv" // "strings" // "time" diff --git a/octoprintApis/FullStateRequest.go b/octoprintApis/FullStateRequest.go index 80a2c431..f77f11b7 100755 --- a/octoprintApis/FullStateRequest.go +++ b/octoprintApis/FullStateRequest.go @@ -4,7 +4,6 @@ import ( // "bytes" "encoding/json" "fmt" - // "log" "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/JobRequest.go b/octoprintApis/JobRequest.go index 8e5d614c..c8a6808e 100755 --- a/octoprintApis/JobRequest.go +++ b/octoprintApis/JobRequest.go @@ -4,7 +4,6 @@ import ( // "bytes" "encoding/json" // "io" - // "log" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/NotificationRequest.go b/octoprintApis/NotificationRequest.go index df2be2f6..3da608d1 100755 --- a/octoprintApis/NotificationRequest.go +++ b/octoprintApis/NotificationRequest.go @@ -4,7 +4,6 @@ import ( // "bytes" "encoding/json" "fmt" - // "log" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/OctoScreenSettingsRequest.go b/octoprintApis/OctoScreenSettingsRequest.go index a612a816..0ca89741 100755 --- a/octoprintApis/OctoScreenSettingsRequest.go +++ b/octoprintApis/OctoScreenSettingsRequest.go @@ -3,7 +3,6 @@ package octoprintApis import ( "encoding/json" "fmt" - //"log" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/PauseRequest.go b/octoprintApis/PauseRequest.go index ca6c6c28..e4b97ebf 100755 --- a/octoprintApis/PauseRequest.go +++ b/octoprintApis/PauseRequest.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io" - // "log" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/PluginManagerInfoRequest.go b/octoprintApis/PluginManagerInfoRequest.go index 731190e9..8d93abd8 100755 --- a/octoprintApis/PluginManagerInfoRequest.go +++ b/octoprintApis/PluginManagerInfoRequest.go @@ -3,8 +3,8 @@ package octoprintApis import ( "bytes" "encoding/json" - "log" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -22,21 +22,21 @@ func (this *PluginManagerInfoRequest) Do(client *Client, uiState string) (*dataM params := bytes.NewBuffer(nil) if err := json.NewEncoder(params).Encode(this); err != nil { - log.Println("plugin_manager.Do() - Encode() failed") + logger.LogError("PluginManagerInfoRequest.Do()", "json.NewEncoder(params).Encode(this)", err) return nil, err } - b, err := client.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) + bytes, err := client.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors) if err != nil { - log.Println("plugin_manager.Do() - doJsonRequest() failed") + logger.LogError("PluginManagerInfoRequest.Do()", "client.doJsonRequest()", err) return nil, err } - r := &dataModels.PluginManagerInfoResponse{} - if err := json.Unmarshal(b, r); err != nil { - log.Println("plugin_manager.Do() - Unmarshal() failed") + response := &dataModels.PluginManagerInfoResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + logger.LogError("PluginManagerInfoRequest.Do()", "json.Unmarshal()", err) return nil, err } - return r, err + return response, err } diff --git a/octoprintApis/PrintHeadHomeRequest.go b/octoprintApis/PrintHeadHomeRequest.go index 2f565819..2a677678 100755 --- a/octoprintApis/PrintHeadHomeRequest.go +++ b/octoprintApis/PrintHeadHomeRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/PrintHeadJogRequest.go b/octoprintApis/PrintHeadJogRequest.go index ee0c3714..bd4b93e0 100755 --- a/octoprintApis/PrintHeadJogRequest.go +++ b/octoprintApis/PrintHeadJogRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/RestartRequest.go b/octoprintApis/RestartRequest.go index 5b4c9b20..df117ce6 100755 --- a/octoprintApis/RestartRequest.go +++ b/octoprintApis/RestartRequest.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" // "io" - // "log" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/RunZOffsetCalibrationRequest.go b/octoprintApis/RunZOffsetCalibrationRequest.go index 415089c5..18d9d46f 100755 --- a/octoprintApis/RunZOffsetCalibrationRequest.go +++ b/octoprintApis/RunZOffsetCalibrationRequest.go @@ -4,7 +4,8 @@ import ( "bytes" "encoding/json" // "fmt" - "log" + + "github.com/Z-Bolt/OctoScreen/logger" ) @@ -12,15 +13,15 @@ type RunZOffsetCalibrationRequest struct { Command string `json:"command"` } -func (cmd *RunZOffsetCalibrationRequest) Do(c *Client) error { - cmd.Command = "run_zoffset_calibration" +func (this *RunZOffsetCalibrationRequest) Do(client *Client) error { + this.Command = "run_zoffset_calibration" - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(cmd); err != nil { - log.Println("zbolt.Do() 1 - NewEncoder() failed") + bytes := bytes.NewBuffer(nil) + if err := json.NewEncoder(bytes).Encode(this); err != nil { + logger.LogError("RunZOffsetCalibrationRequest.Do()", "json.NewEncoder(params).Encode(this)", err) return err } - _, err := c.doJsonRequest("POST", PluginZBoltOctoScreenApiUri, b, ConnectionErrors) + _, err := client.doJsonRequest("POST", PluginZBoltOctoScreenApiUri, bytes, ConnectionErrors) return err } diff --git a/octoprintApis/SdInitRequest.go b/octoprintApis/SdInitRequest.go index 8231f6a8..fcfe2122 100755 --- a/octoprintApis/SdInitRequest.go +++ b/octoprintApis/SdInitRequest.go @@ -5,7 +5,6 @@ import ( // "encoding/json" // "fmt" // "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/SdRefreshRequest.go b/octoprintApis/SdRefreshRequest.go index c8fdb270..92c6dbf4 100755 --- a/octoprintApis/SdRefreshRequest.go +++ b/octoprintApis/SdRefreshRequest.go @@ -5,7 +5,6 @@ import ( // "encoding/json" // "fmt" // "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/SdReleaseRequest.go b/octoprintApis/SdReleaseRequest.go index 15156368..d7a1b4a7 100755 --- a/octoprintApis/SdReleaseRequest.go +++ b/octoprintApis/SdReleaseRequest.go @@ -5,7 +5,6 @@ import ( // "encoding/json" // "fmt" // "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/SdStateRequest.go b/octoprintApis/SdStateRequest.go index b2e6afa2..87c87179 100755 --- a/octoprintApis/SdStateRequest.go +++ b/octoprintApis/SdStateRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" // "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/StartRequest.go b/octoprintApis/StartRequest.go index 475ad1bf..b1a7638f 100755 --- a/octoprintApis/StartRequest.go +++ b/octoprintApis/StartRequest.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" // "io" - // "log" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) diff --git a/octoprintApis/StatusMapping.go b/octoprintApis/StatusMapping.go index 8591e05c..d49ed4b9 100755 --- a/octoprintApis/StatusMapping.go +++ b/octoprintApis/StatusMapping.go @@ -5,7 +5,6 @@ import ( "fmt" // "io" // "io/ioutil" - // "log" // "net/http" // "net/url" // "time" diff --git a/octoprintApis/TemperatureDataRequest.go b/octoprintApis/TemperatureDataRequest.go index 5a66c484..2bca238e 100755 --- a/octoprintApis/TemperatureDataRequest.go +++ b/octoprintApis/TemperatureDataRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" // "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolExtrudeRequest.go b/octoprintApis/ToolExtrudeRequest.go index eecf50fe..58942bf2 100755 --- a/octoprintApis/ToolExtrudeRequest.go +++ b/octoprintApis/ToolExtrudeRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolFlowRateRequest.go b/octoprintApis/ToolFlowRateRequest.go index c3f78420..804ea5f4 100755 --- a/octoprintApis/ToolFlowRateRequest.go +++ b/octoprintApis/ToolFlowRateRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolOffsetRequest.go b/octoprintApis/ToolOffsetRequest.go index 2dbf71a7..0ae6aa54 100755 --- a/octoprintApis/ToolOffsetRequest.go +++ b/octoprintApis/ToolOffsetRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolSelectRequest.go b/octoprintApis/ToolSelectRequest.go index 7716d9a6..2451457a 100755 --- a/octoprintApis/ToolSelectRequest.go +++ b/octoprintApis/ToolSelectRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolStateRequest.go b/octoprintApis/ToolStateRequest.go index 353d0acf..b491344a 100755 --- a/octoprintApis/ToolStateRequest.go +++ b/octoprintApis/ToolStateRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" // "io" - // "log" // "strings" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ToolTargetRequest.go b/octoprintApis/ToolTargetRequest.go index 546bbb99..34678c05 100755 --- a/octoprintApis/ToolTargetRequest.go +++ b/octoprintApis/ToolTargetRequest.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/ZOffsetRequest.go b/octoprintApis/ZOffsetRequest.go index cd6eb12b..bd456dc4 100755 --- a/octoprintApis/ZOffsetRequest.go +++ b/octoprintApis/ZOffsetRequest.go @@ -4,8 +4,8 @@ import ( "bytes" "encoding/json" // "fmt" - "log" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -15,29 +15,29 @@ type ZOffsetRequest struct { Tool int `json:"tool"` } -func (cmd *ZOffsetRequest) Do(c *Client) (*dataModels.ZOffsetResponse, error) { - cmd.Command = "get_z_offset" +func (this *ZOffsetRequest) Do(client *Client) (*dataModels.ZOffsetResponse, error) { + this.Command = "get_z_offset" params := bytes.NewBuffer(nil) - if err := json.NewEncoder(params).Encode(cmd); err != nil { - log.Println("zbolt.Do() 3 - Encode() failed") + if err := json.NewEncoder(params).Encode(this); err != nil { + logger.LogError("ZOffsetRequest.Do()", "json.NewEncoder(params).Encode(this)", err) return nil, err } - // b, err := c.doJsonRequest("POST", URIZBoltRequest, params, ConnectionErrors) - b, err := c.doJsonRequest("GET", PluginZBoltApiUri, params, ConnectionErrors) + // b, err := client.doJsonRequest("POST", URIZBoltRequest, params, ConnectionErrors) + bytes, err := client.doJsonRequest("GET", PluginZBoltApiUri, params, ConnectionErrors) if err != nil { - log.Println("zbolt.Do() 3 - doJsonRequest() failed") + logger.LogError("ZOffsetRequest.Do()", "client.doJsonRequest()", err) return nil, err } - r := &dataModels.ZOffsetResponse{} - if err := json.Unmarshal(b, r); err != nil { - log.Println("zbolt.Do() 3 - Unmarshal() failed") + response := &dataModels.ZOffsetResponse{} + if err := json.Unmarshal(bytes, response); err != nil { + logger.LogError("ZOffsetRequest.Do()", "json.Unmarshal()", err) return nil, err } - return r, err + return response, err } @@ -50,15 +50,15 @@ type SetZOffsetRequest struct { Value float64 `json:"value"` } -func (cmd *SetZOffsetRequest) Do(c *Client) error { - cmd.Command = "set_z_offset" +func (this *SetZOffsetRequest) Do(client *Client) error { + this.Command = "set_z_offset" - b := bytes.NewBuffer(nil) - if err := json.NewEncoder(b).Encode(cmd); err != nil { - log.Println("zbolt.Do() 2 - Encode() failed") + bytes := bytes.NewBuffer(nil) + if err := json.NewEncoder(bytes).Encode(this); err != nil { + logger.LogError("SetZOffsetRequest.Do()", "json.NewEncoder(params).Encode(this)", err) return err } - _, err := c.doJsonRequest("POST", PluginZBoltApiUri, b, ConnectionErrors) + _, err := client.doJsonRequest("POST", PluginZBoltApiUri, bytes, ConnectionErrors) return err } diff --git a/octoprintApis/client.go b/octoprintApis/client.go index c3bac81e..9fed9455 100755 --- a/octoprintApis/client.go +++ b/octoprintApis/client.go @@ -5,11 +5,11 @@ import ( "fmt" "io" "io/ioutil" - // "log" "net/http" "net/url" "time" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -53,20 +53,22 @@ func (this *Client) doJsonRequest( body io.Reader, statusMapping StatusMapping, ) ([]byte, error) { - LogMessagef(" entering Client.doJsonRequest()") + logger.TraceEnter("Client.doJsonRequest()") bytes, err := this.doRequest(method, target, "application/json", body, statusMapping) if err != nil { - LogError(err, "Client.doJsonRequest(), this.doRequest() failed") - LogMessagef(" leaving Client.doJsonRequest()") + logger.LogError("Client.doJsonRequest()", "this.doRequest()", err) + logger.TraceLeave("Client.doJsonRequest()") return nil, err } - // Use the following for debugging. Comment out for production. - json := string(bytes) - LogMessagef(" JSON response: %s", json) - LogMessagef(" leaving Client.doJsonRequest()") + // Use the following only for debugging. + if logger.LogLevel() == "debug" { + json := string(bytes) + logger.Debugf("JSON response: %s", json) + } + logger.TraceLeave("Client.doJsonRequest()") return bytes, err } @@ -77,15 +79,15 @@ func (this *Client) doRequest( body io.Reader, statusMapping StatusMapping, ) ([]byte, error) { - LogMessagef(" entering Client.doRequest()") - LogMessagef(" method: %s", method) - LogMessagef(" target: %s",target) + logger.TraceEnter("Client.doRequest()") + logger.Debugf("method: %s", method) + logger.Debugf("target: %s",target) req, err := http.NewRequest(method, joinUrl(this.Endpoint, target), body) if err != nil { - LogError(err, "Client.doRequest(), http.NewRequest() failed") - LogMessagef(" leaving Client.doRequest()") + logger.LogError("Client.doRequest()", "http.NewRequest()", err) + logger.TraceLeave("Client.doRequest()") return nil, err } @@ -99,22 +101,23 @@ func (this *Client) doRequest( req.Header.Add("X-Api-Key", this.APIKey) resp, err := this.httpClient.Do(req) if err != nil { - LogError(err, "Client.doRequest(), this.httpClient.Do() failed") - LogMessagef(" leaving Client.doRequest()") + logger.LogError("Client.doRequest()", "this.httpClient.Do()", err) + logger.TraceLeave("Client.doRequest()") return nil, err } response, err := this.handleResponse(resp, statusMapping) if err != nil { - LogError(err, "Client.doRequest(), this.handleResponse() failed") - LogMessagef(" leaving Client.doRequest()") + logger.LogError("Client.doRequest()", "this.handleResponse()", err) + logger.TraceLeave("Client.doRequest()") return nil, err } - LogMessagef(" leaving Client.doRequest()") + logger.TraceLeave("Client.doRequest()") return response, err } + func (this *Client) handleResponse( httpResponse *http.Response, statusMapping StatusMapping, diff --git a/octoprintApis/dataModels/FileResponse.go b/octoprintApis/dataModels/FileResponse.go index dff3d3d1..2b50756b 100755 --- a/octoprintApis/dataModels/FileResponse.go +++ b/octoprintApis/dataModels/FileResponse.go @@ -3,7 +3,6 @@ package dataModels import ( // "encoding/json" // "fmt" - // "log" // "strconv" // "strings" // "time" diff --git a/octoprintApis/debugUtils.go b/octoprintApis/debugUtils.go deleted file mode 100755 index aa353ffb..00000000 --- a/octoprintApis/debugUtils.go +++ /dev/null @@ -1,36 +0,0 @@ -package octoprintApis - -import ( - "log" -) - - - -var EnableApiLogging = false - - -func LogError(err error, msg string) { - if EnableApiLogging { - log.Printf("ERROR!!! %s", err.Error()) - log.Printf("Message: %s", msg) - } -} - - -func LogMessage(v ...interface{}) { - if EnableApiLogging { - log.Print(v...) - } -} - -func LogMessagef(format string, v ...interface{}) { - if EnableApiLogging { - log.Printf(format, v...) - } -} - -func LogMessageln(v ...interface{}) { - if EnableApiLogging { - log.Println(v...) - } -} diff --git a/octoprintApis/job.go b/octoprintApis/job.go index 9dd70398..c6dbb4f4 100755 --- a/octoprintApis/job.go +++ b/octoprintApis/job.go @@ -4,7 +4,6 @@ import ( // "bytes" // "encoding/json" // "io" - // "log" ) diff --git a/octoprintApis/printer.go b/octoprintApis/printer.go index 3d58a8b9..bf3ef79c 100755 --- a/octoprintApis/printer.go +++ b/octoprintApis/printer.go @@ -5,7 +5,6 @@ import ( "encoding/json" // "fmt" // "io" - // "log" // "strings" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" diff --git a/octoprintApis/zbolt.go b/octoprintApis/zbolt.go index 96559215..c6ca739c 100755 --- a/octoprintApis/zbolt.go +++ b/octoprintApis/zbolt.go @@ -4,7 +4,6 @@ import ( // "bytes" // "encoding/json" // "fmt" - // "log" ) diff --git a/ui/BedLevelPanel.go b/ui/BedLevelPanel.go index d4f1fb94..b96290fc 100755 --- a/ui/BedLevelPanel.go +++ b/ui/BedLevelPanel.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -105,23 +106,21 @@ func (this *bedLevelPanel) addBedLevelCornerButton(isLeft, isTop bool) { } func (this *bedLevelPanel) defineLevelingPoints() { - utils.Logger.Debug("entering BedLevelPanel.verifyConnection()") + logger.TraceEnter("BedLevelPanel.defineLevelingPoints()") connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("BedLevelPanel.defineLevelingPoints()", "version.Get()", err) - - utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()") + logger.LogError("BedLevelPanel.defineLevelingPoints()", "version.Get()", err) + logger.TraceLeave("BedLevelPanel.defineLevelingPoints()") return } - utils.Logger.Info(connectionResponse.Current.PrinterProfile) + logger.Info(connectionResponse.Current.PrinterProfile) printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(this.UI.Client) if err != nil { - utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(PrinterProfilesRequest)", err) - - utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()") + logger.LogError("BedLevelPanel.defineLevelingPoints()", "Do(PrinterProfilesRequest)", err) + logger.TraceLeave("BedLevelPanel.defineLevelingPoints()") return } @@ -137,7 +136,7 @@ func (this *bedLevelPanel) defineLevelingPoints() { "b-r": {xMax - xOffset, yOffset}, } - utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()") + logger.TraceLeave("BedLevelPanel.defineLevelingPoints()") } func (this *bedLevelPanel) createLevelButton(placement string) *gtk.Button { @@ -154,7 +153,7 @@ func (this *bedLevelPanel) createLevelButton(placement string) *gtk.Button { } if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("BedLevelPanel.createLevelButton()", "Do(CommandRequest)", err) + logger.LogError("BedLevelPanel.createLevelButton()", "Do(CommandRequest)", err) return } }) @@ -173,7 +172,7 @@ func (this *bedLevelPanel) goHomeIfRequired() { } if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("BedLevelPanel.goHomeIfRequire()", "Do(CommandRequest)", err) + logger.LogError("BedLevelPanel.goHomeIfRequire()", "Do(CommandRequest)", err) return } @@ -188,7 +187,7 @@ func (this *bedLevelPanel) createAutoLevelButton(gcode string) *gtk.Button { } if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("BedLevelPanel.createAutoLevelButton()", "Do(CommandRequest)", err) + logger.LogError("BedLevelPanel.createAutoLevelButton()", "Do(CommandRequest)", err) return } }) diff --git a/ui/ControlPanel.go b/ui/ControlPanel.go index de4667b6..b4279d94 100755 --- a/ui/ControlPanel.go +++ b/ui/ControlPanel.go @@ -5,10 +5,11 @@ import ( // "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" - "github.com/Z-Bolt/OctoScreen/utils" + // "github.com/Z-Bolt/OctoScreen/utils" ) var controlPanelInstance *controlPanel @@ -73,10 +74,10 @@ func (this *controlPanel) getDefaultControls() []*dataModels.ControlDefinition { func (this *controlPanel) getCustomControls() []*dataModels.ControlDefinition { controlDefinitions := []*dataModels.ControlDefinition{} - utils.Logger.Info("control.getCustomControl() - Retrieving custom controls") + logger.Info("control.getCustomControl() - Retrieving custom controls") response, err := (&octoprintApis.CustomCommandsRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("control.getCustomControl()", "Do(ControlDefinition)", err) + logger.LogError("control.getCustomControl()", "Do(ControlDefinition)", err) return controlDefinitions } @@ -92,10 +93,10 @@ func (this *controlPanel) getCustomControls() []*dataModels.ControlDefinition { } func (this *controlPanel) getCommands() []*dataModels.CommandDefinition { - utils.Logger.Info("Retrieving custom commands") + logger.Info("Retrieving custom commands") response, err := (&octoprintApis.SystemCommandsRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("control.getCommands()", "Do(SystemCommandsRequest)", err) + logger.LogError("control.getCommands()", "Do(SystemCommandsRequest)", err) return nil } diff --git a/ui/FatalErrorWindow.go b/ui/FatalErrorWindow.go index ce387762..5fbea62f 100755 --- a/ui/FatalErrorWindow.go +++ b/ui/FatalErrorWindow.go @@ -2,13 +2,14 @@ package ui import ( "github.com/gotk3/gotk3/gtk" - "github.com/Z-Bolt/OctoScreen/utils" + "github.com/Z-Bolt/OctoScreen/logger" + // "github.com/Z-Bolt/OctoScreen/utils" ) func CreateFatalErrorWindow(message string, description string) *gtk.Window { window, error := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) if error != nil { - utils.LogFatalError("fatal_error_window.CreateFatalErrorWindow()", "WindowNew()", error) + logger.LogFatalError("FatalErrorWindow.CreateFatalErrorWindow()", "WindowNew()", error) } window.SetTitle("Fatal Error") @@ -21,7 +22,7 @@ func CreateFatalErrorWindow(message string, description string) *gtk.Window { // Create a new label widget to show in the window. label, error := gtk.LabelNew("\n " + message + "\n " + description) if error != nil { - utils.LogFatalError("fatal_error_window.CreateFatalErrorWindow()", "LabelNew()", error) + logger.LogFatalError("FatalErrorWindow.CreateFatalErrorWindow()", "LabelNew()", error) } label.SetHAlign(gtk.ALIGN_START) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index f2f490aa..abbedfc5 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -9,6 +9,7 @@ import ( "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" // "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -116,7 +117,7 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { } current := this.locationHistory.CurrentLocation() - utils.Logger.Info("Loading list of files from: ", string(current)) + logger.Infof("Loading list of files from: %s", string(current)) filesRequest := &octoprintApis.FilesRequest { Location: current, @@ -124,7 +125,7 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { } filesResponse, err := filesRequest.Do(this.UI.Client) if err != nil { - utils.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) + logger.LogError("files.getSortedFiles()", "Do(FilesRequest)", err) files = []*dataModels.FileResponse{} } else { files = filesResponse.Files @@ -383,9 +384,9 @@ func (this *filesPanel) createListItemButton( selectFileRequest.Path = fileResponse.Path selectFileRequest.Print = true - utils.Logger.Infof("Loading file %q", fileResponse.Name) + logger.Infof("Loading file %q", fileResponse.Name) if err := selectFileRequest.Do(this.UI.Client); err != nil { - utils.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) + logger.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err) return } })) @@ -438,14 +439,14 @@ func (this *filesPanel) addThumbnail( listItemBox *gtk.Box, ) { if fileResponse.Thumbnail != "" { - utils.Logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) + logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail) - utils.Logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) + logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) if imageFromUrlErr == nil { - utils.Logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it...") + logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it...") bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) diff --git a/ui/HttpRequestTestWindow.go b/ui/HttpRequestTestWindow.go index 3033fbcb..e4bc00ba 100755 --- a/ui/HttpRequestTestWindow.go +++ b/ui/HttpRequestTestWindow.go @@ -3,7 +3,6 @@ package ui import ( "fmt" // "io/ioutil" - // standardLog "log" // "os" // "os/user" // "path/filepath" @@ -13,11 +12,11 @@ import ( "github.com/coreos/go-systemd/daemon" "github.com/gotk3/gotk3/gtk" - // "github.com/sirupsen/logrus" - // "github.com/Z-Bolt/OctoScreen/ui" + + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" + // "github.com/Z-Bolt/OctoScreen/ui" "github.com/Z-Bolt/OctoScreen/utils" - // "gopkg.in/yaml.v1" ) @@ -36,7 +35,7 @@ func CreateHttpRequestTestWindow( width int, height int, ) *HttpRequestTestWindow { - utils.Logger.Debug("entering CreateHttpRequestTestWindow()") + logger.TraceEnter("CreateHttpRequestTestWindow()") instance := &HttpRequestTestWindow { @@ -53,13 +52,9 @@ func CreateHttpRequestTestWindow( instance.addControls() defer instance.Window.ShowAll() + instance.sdNotify(daemon.SdNotifyReady) - instance.sdNotify("READY=1") - //instance.sdNotify(daemon.SdNotifyReady) - - - utils.Logger.Debug("leaving CreateHttpRequestTestWindow()") - + logger.TraceLeave("CreateHttpRequestTestWindow()") return instance } @@ -70,7 +65,7 @@ func (this *HttpRequestTestWindow) createWindow( ) { window, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) if err != nil { - utils.LogFatalError("createWindow()", "WindowNew()", err) + logger.LogFatalError("createWindow()", "WindowNew()", err) } this.Window = window @@ -81,7 +76,7 @@ func (this *HttpRequestTestWindow) createWindow( this.Window.Connect("show", this.BackgroundTask.Start) this.Window.Connect("destroy", func() { - utils.Logger.Debug("destroy() callback was called") + logger.Debug("destroy() callback was called") gtk.MainQuit() }) } @@ -91,7 +86,7 @@ func (this *HttpRequestTestWindow) addControls() { // Create a new label widget to show in the window. label, err := gtk.LabelNew("") if err != nil { - utils.LogFatalError("CreateHttpRequestTestWindow()", "LabelNew()", err) + logger.LogFatalError("CreateHttpRequestTestWindow()", "LabelNew()", err) } this.Label = label @@ -102,50 +97,48 @@ func (this *HttpRequestTestWindow) addControls() { func (this *HttpRequestTestWindow) updateTestWindow() { - utils.Logger.Debug("entering updateTestWindow()") - + logger.TraceEnter("updateTestWindow()") this.UpdateCount++ strUpdateCount := fmt.Sprintf("UpdateCount: %d", this.UpdateCount) - utils.Logger.Debug(strUpdateCount) + logger.Debug(strUpdateCount) this.Label.SetLabel(strUpdateCount) //this.checkNotification() this.verifyConnection() - utils.Logger.Debug("leaving updateTestWindow()") + logger.TraceLeave("updateTestWindow()") } func (this *HttpRequestTestWindow) verifyConnection() { - utils.Logger.Debug("entering verifyConnection()") + logger.TraceEnter("verifyConnection()") - this.sdNotify("WATCHDOG=1") - //this.sdNotify(daemon.SdNotifyWatchdog) + this.sdNotify(daemon.SdNotifyWatchdog) connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) if err != nil { - utils.LogError("verifyConnection()", "ConnectionRequest.Do()", err) + logger.LogError("verifyConnection()", "ConnectionRequest.Do()", err) } else { strCurrentState := string(connectionResponse.Current.State) - utils.Logger.Debugf(" verifyConnection() succeeded") - utils.Logger.Debugf(" connectionResponse.Current.State is %q", strCurrentState) + logger.Debugf("verifyConnection() succeeded") + logger.Debugf("connectionResponse.Current.State is %q", strCurrentState) } - utils.Logger.Debug("leaving verifyConnection()") + logger.TraceLeave("verifyConnection()") } func (this *HttpRequestTestWindow) sdNotify(state string) { - utils.Logger.Debug("entering sdNotify()") + logger.TraceEnter("sdNotify()") _, err := daemon.SdNotify(false, state) if err != nil { - utils.Logger.Errorf("sdNotify()", "SdNotify()", err) - utils.Logger.Debug("leaving sdNotify()") + logger.Errorf("sdNotify()", "SdNotify()", err) + logger.TraceLeave("sdNotify()") return } - utils.Logger.Debug("leaving sdNotify()") + logger.TraceLeave("sdNotify()") } diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go index 2ed05b86..a9bf56f5 100755 --- a/ui/IdleStatusPanel.go +++ b/ui/IdleStatusPanel.go @@ -8,6 +8,7 @@ import ( "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -40,34 +41,32 @@ func IdleStatusPanel(ui *UI) *idleStatusPanel { } func (this *idleStatusPanel) initialize() { - utils.Logger.Debug("entering IdleStatusPanel.initialize()") + logger.TraceEnter("IdleStatusPanel.initialize()") defer this.Initialize() - utils.Logger.Info("IdleStatusPanel.initialize() - settings are:") + logger.Info("IdleStatusPanel.initialize() - settings are:") if this.UI == nil { - utils.Logger.Error("IdleStatusPanel.initialize() - this.UI is nil") + logger.Error("IdleStatusPanel.initialize() - this.UI is nil") } else if this.UI.Settings == nil { - utils.Logger.Error("IdleStatusPanel.initialize() - this.UI.Settings is nil") + logger.Error("IdleStatusPanel.initialize() - this.UI.Settings is nil") } else { - utils.Logger.Info("struct values:") - utils.Logger.Info(this.UI.Settings) + logger.Info("struct values:") + logger.Info(this.UI.Settings) jsonStr, err := utils.StructToJson(this.UI.Settings) if err == nil { - utils.Logger.Info("JSON:") - utils.Logger.Info(jsonStr) + logger.Info("JSON:") + logger.Info(jsonStr) } } - utils.Logger.Info("") - utils.Logger.Info("") var menuItems []dataModels.MenuItem if this.UI.Settings == nil || this.UI.Settings.MenuStructure == nil || len(this.UI.Settings.MenuStructure) < 1 { - utils.Logger.Info("IdleStatusPanel.initialize() - Loading default menu") + logger.Info("IdleStatusPanel.initialize() - Loading default menu") this.UI.Settings.MenuStructure = getDefaultMenuItems(this.UI.Client) } else { - utils.Logger.Info("IdleStatusPanel.initialize() - Loading octo menu") + logger.Info("IdleStatusPanel.initialize() - Loading octo menu") } menuItems = this.UI.Settings.MenuStructure @@ -83,27 +82,27 @@ func (this *idleStatusPanel) initialize() { this.showTools() - utils.Logger.Debug("leaving IdleStatusPanel.initialize()") + logger.TraceLeave("IdleStatusPanel.initialize()") } func (this *idleStatusPanel) showFiles() { - utils.Logger.Debug("entering IdleStatusPanel.showFiles()") + logger.TraceEnter("IdleStatusPanel.showFiles()") this.UI.GoToPanel(FilesPanel(this.UI, this)) - utils.Logger.Debug("leaving IdleStatusPanel.showFiles()") + logger.TraceLeave("IdleStatusPanel.showFiles()") } func (this *idleStatusPanel) update() { - utils.Logger.Debug("entering IdleStatusPanel.update()") + logger.TraceEnter("IdleStatusPanel.update()") this.updateTemperature() - utils.Logger.Debug("leaving IdleStatusPanel.update()") + logger.TraceLeave("IdleStatusPanel.update()") } func (this *idleStatusPanel) showTools() { - utils.Logger.Debug("entering IdleStatusPanel.showTools()") + logger.TraceEnter("IdleStatusPanel.showTools()") // Note: The creation and initialization of the tool buttons in IdleStatusPanel and // PrintStatusPanel look similar, but there are subtle differences between the two @@ -147,17 +146,16 @@ func (this *idleStatusPanel) showTools() { this.Grid().Attach(this.bedButton, 0, 2, 2, 1) } - utils.Logger.Debug("leaving IdleStatusPanel.showTools()") + logger.TraceLeave("IdleStatusPanel.showTools()") } func (this *idleStatusPanel) updateTemperature() { - utils.Logger.Debug("entering IdleStatusPanel.updateTemperature()") + logger.TraceEnter("IdleStatusPanel.updateTemperature()") fullStateResponse, err := (&octoprintApis.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) if err != nil { - utils.LogError("IdleStatusPanel.updateTemperature()", "Do(StateRequest)", err) - - utils.Logger.Debug("leaving IdleStatusPanel.updateTemperature()") + logger.LogError("IdleStatusPanel.updateTemperature()", "Do(StateRequest)", err) + logger.TraceLeave("IdleStatusPanel.updateTemperature()") return } @@ -180,5 +178,5 @@ func (this *idleStatusPanel) updateTemperature() { } } - utils.Logger.Debug("leaving IdleStatusPanel.updateTemperature()") + logger.TraceLeave("IdleStatusPanel.updateTemperature()") } diff --git a/ui/NetworkPanel.go b/ui/NetworkPanel.go index ce47c68a..ffeb0166 100755 --- a/ui/NetworkPanel.go +++ b/ui/NetworkPanel.go @@ -6,10 +6,11 @@ import ( "time" "github.com/gotk3/gotk3/gtk" - "pifke.org/wpasupplicant" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/uiWidgets" "github.com/Z-Bolt/OctoScreen/utils" + "pifke.org/wpasupplicant" ) var networkPanelInstance *networkPanel @@ -47,10 +48,14 @@ func (this *networkPanel) initialize() { } func (this *networkPanel) update() { + logger.TraceEnter("networkPanel.update()") + utils.EmptyTheContainer(&this.listBox.Container) this.setNetStatusText() this.setNetworkItems() this.listBox.ShowAll() + + logger.TraceLeave("networkPanel.update()") } func (this *networkPanel) setNetStatusText() { @@ -139,7 +144,7 @@ func (this *networkPanel) setNetworkListItems(wpa wpasupplicant.Conn) { err := wpa.Scan() if err != nil { - utils.LogError("NetworkPanel.update()", "Scan()", err) + logger.LogError("NetworkPanel.update()", "Scan()", err) } } else { label := utils.MustLabel("\n\nWiFi management is not available\non this hardware") diff --git a/ui/PrintStatusPanel.go b/ui/PrintStatusPanel.go index 145877b6..8a82bcba 100755 --- a/ui/PrintStatusPanel.go +++ b/ui/PrintStatusPanel.go @@ -6,6 +6,7 @@ import ( "time" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -158,17 +159,17 @@ func (this *printStatusPanel) createPauseButton() gtk.IWidget { this.pauseButton = utils.MustButtonImageStyle("Pause", "pause.svg", "color-warning-sign-yellow", func() { defer this.updateTemperature() - utils.Logger.Info("Pausing/Resuming job") + logger.Info("Pausing/Resuming job") cmd := &octoprintApis.PauseRequest{Action: dataModels.Toggle} err := cmd.Do(this.UI.Client) - utils.Logger.Info("Pausing/Resuming job 2, Do() was just called") + logger.Info("Pausing/Resuming job 2, Do() was just called") if err != nil { - utils.LogError("print_status.createPauseButton()", "Do(PauseRequest)", err) + logger.LogError("print_status.createPauseButton()", "Do(PauseRequest)", err) return } - utils.Logger.Info("Pausing/Resuming job 2c") + logger.Info("Pausing/Resuming job 2c") }) return this.pauseButton @@ -198,20 +199,21 @@ func (this *printStatusPanel) createControlButton() gtk.IWidget { } func (this *printStatusPanel) update() { - //Logger.Printf("Now in print_status.update()") + logger.TraceEnter("printStatusPanel.update()") this.updateTemperature() this.updateJob() - //Logger.Printf("Now leaving print_status.update()") + logger.TraceLeave("printStatusPanel.update()") } func (this *printStatusPanel) updateTemperature() { - //Logger.Printf("Now in print_status.updateTemperature()") + logger.TraceEnter("printStatusPanel.updateTemperature()") fullStateResponse, err := (&octoprintApis.FullStateRequest{Exclude: []string{"sd"}}).Do(this.UI.Client) if err != nil { - utils.LogError("print_status.updateTemperature()", "Do(StateRequest)", err) + logger.LogError("print_status.updateTemperature()", "Do(StateRequest)", err) + logger.TraceLeave("printStatusPanel.updateTemperature()") return } @@ -237,7 +239,7 @@ func (this *printStatusPanel) updateTemperature() { } } - //Logger.Printf("Now leaving print_status.updateTemperature()") + logger.TraceLeave("printStatusPanel.updateTemperature()") } func (this *printStatusPanel) doUpdateState(printerState *dataModels.PrinterState) { @@ -283,9 +285,9 @@ func (this *printStatusPanel) doUpdateState(printerState *dataModels.PrinterStat this.completeButton.Show() default: - logLevel := utils.LowerCaseLogLevel() + logLevel := logger.LogLevel() if logLevel == "debug" { - utils.Logger.Fatalf("PrintStatusPanel.doUpdateState() - unknown printerState.Flags") + logger.Fatalf("PrintStatusPanel.doUpdateState() - unknown printerState.Flags") } this.pauseButton.SetSensitive(false) @@ -298,11 +300,12 @@ func (this *printStatusPanel) doUpdateState(printerState *dataModels.PrinterStat } func (this *printStatusPanel) updateJob() { - //Logger.Printf("Now in print_status.updateJob()") + logger.TraceEnter("printStatusPanel.updateJob()") jobResponse, err := (&octoprintApis.JobRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("print_status.updateJob()", "Do(JobRequest)", err) + logger.LogError("print_status.updateJob()", "Do(JobRequest)", err) + logger.TraceLeave("printStatusPanel.updateJob()") return } @@ -328,7 +331,7 @@ func (this *printStatusPanel) updateJob() { timeLeft = "" default: - utils.Logger.Info(jobResponse.Progress.PrintTime) + logger.Info(jobResponse.Progress.PrintTime) printTime := time.Duration(int64(jobResponse.Progress.PrintTime) * 1e9) printTimeLeft := time.Duration(int64(jobResponse.Progress.PrintTimeLeft) * 1e9) timeSpent = fmt.Sprintf("Time: %s", printTime) @@ -338,7 +341,7 @@ func (this *printStatusPanel) updateJob() { this.timeLabel.Label.SetLabel(timeSpent) this.timeLeftLabel.Label.SetLabel(timeLeft) - //Logger.Printf("Now leaving print_status.updateJob()") + logger.TraceLeave("printStatusPanel.updateJob()") } func confirmStopDialogBox( @@ -369,9 +372,9 @@ func confirmStopDialogBox( userResponse := dialogBox.Run() if userResponse == int(gtk.RESPONSE_YES) { - utils.Logger.Warning("Stopping job") + logger.Warn("Stopping job") if err := (&octoprintApis.CancelRequest{}).Do(printStatusPanel.UI.Client); err != nil { - utils.LogError("print_status.confirmStopDialogBox()", "Do(CancelRequest)", err) + logger.LogError("print_status.confirmStopDialogBox()", "Do(CancelRequest)", err) return } } diff --git a/ui/SplashPanel.go b/ui/SplashPanel.go index acb2e1d2..2e3e80e1 100755 --- a/ui/SplashPanel.go +++ b/ui/SplashPanel.go @@ -3,6 +3,7 @@ package ui import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -22,7 +23,7 @@ func NewSplashPanel(ui *UI) *SplashPanel { } func (this *SplashPanel) initialize() { - utils.Logger.Debug("entering SplashPanel.initialize()") + logger.TraceEnter("SplashPanel.initialize()") logo := utils.MustImageFromFile("logos/logo.png") this.Label = utils.MustLabel("...") @@ -48,11 +49,11 @@ func (this *SplashPanel) initialize() { this.Grid().Add(box) - utils.Logger.Debug("leaving SplashPanel.initialize()") + logger.TraceLeave("SplashPanel.initialize()") } func (this *SplashPanel) createActionBar() gtk.IWidget { - utils.Logger.Debug("entering SplashPanel.createActionBar()") + logger.TraceEnter("SplashPanel.createActionBar()") actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) actionBar.SetHAlign(gtk.ALIGN_END) @@ -72,28 +73,27 @@ func (this *SplashPanel) createActionBar() gtk.IWidget { networkButton.SetProperty("width-request", this.Scaled(100)) actionBar.Add(networkButton) - utils.Logger.Debug("leaving SplashPanel.createActionBar()") - + logger.TraceLeave("SplashPanel.createActionBar()") return actionBar } func (this *SplashPanel) putOnHold() { - utils.Logger.Debug("entering SplashPanel.putOnHold()") + logger.TraceEnter("SplashPanel.putOnHold()") this.RetryButton.Show() ctx, err := this.RetryButton.GetStyleContext() if err != nil { - utils.LogError("SplashPanel.putOnHold()", "RetryButton.GetStyleContext()", err) + logger.LogError("SplashPanel.putOnHold()", "RetryButton.GetStyleContext()", err) } else { ctx.RemoveClass("hidden") } this.Label.SetText("Cannot connect to the printer. Tap \"Retry\" to try again.") - utils.Logger.Debug("leaving SplashPanel.putOnHold()") + logger.TraceLeave("SplashPanel.putOnHold()") } func (this *SplashPanel) releaseFromHold() { - utils.Logger.Debug("entering SplashPanel.releaseFromHold()") + logger.TraceEnter("SplashPanel.releaseFromHold()") this.RetryButton.Hide() ctx, _ := this.RetryButton.GetStyleContext() @@ -102,21 +102,21 @@ func (this *SplashPanel) releaseFromHold() { this.Label.SetText("Loading...") this.UI.connectionAttempts = 0 - utils.Logger.Debug("leaving SplashPanel.releaseFromHold()") + logger.TraceLeave("SplashPanel.releaseFromHold()") } func (this *SplashPanel) showNetwork() { - utils.Logger.Debug("entering SplashPanel.showNetwork()") + logger.TraceEnter("SplashPanel.showNetwork()") this.UI.GoToPanel(NetworkPanel(this.UI, this)) - utils.Logger.Debug("leaving SplashPanel.showNetwork()") + logger.TraceLeave("SplashPanel.showNetwork()") } func (this *SplashPanel) showSystem() { - utils.Logger.Debug("entering SplashPanel.showSystem()") + logger.TraceEnter("SplashPanel.showSystem()") this.UI.GoToPanel(SystemPanel(this.UI, this)) - utils.Logger.Debug("leaving SplashPanel.showSystem()") + logger.TraceLeave("SplashPanel.showSystem()") } diff --git a/ui/TemperaturePresetsPanel.go b/ui/TemperaturePresetsPanel.go index 672b9525..47b6df2b 100755 --- a/ui/TemperaturePresetsPanel.go +++ b/ui/TemperaturePresetsPanel.go @@ -2,10 +2,11 @@ package ui import ( "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" - "github.com/Z-Bolt/OctoScreen/utils" + // "github.com/Z-Bolt/OctoScreen/utils" ) var temperaturePresetsPanelInstance *temperaturePresetsPanel @@ -42,7 +43,7 @@ func (this *temperaturePresetsPanel) initialize() { func (this *temperaturePresetsPanel) createTemperaturePresetButtons() { settings, err := (&octoprintApis.SettingsRequest{}).Do(this.UI.Client) if err != nil { - utils.LogError("TemperaturePresetsPanel.getTemperaturePresets()", "Do(SettingsRequest)", err) + logger.LogError("TemperaturePresetsPanel.getTemperaturePresets()", "Do(SettingsRequest)", err) return } diff --git a/ui/menu.go b/ui/menu.go index 10ceb871..7e535551 100755 --- a/ui/menu.go +++ b/ui/menu.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" // "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -72,28 +73,27 @@ func getPanel( case "extrude_multitool": fallthrough case "extruder": - utils.Logger.Warnf("WARNING! the '%s' panel has been deprecated. Please use the 'filament' panel instead.", menuItem.Panel) - utils.Logger.Warnf("Support for the %s panel remains in this release, but will be removed in a future.", menuItem.Panel) - utils.Logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") + logger.Warnf("WARNING! the '%s' panel has been deprecated. Please use the 'filament' panel instead.", menuItem.Panel) + logger.Warnf("Support for the %s panel remains in this release, but will be removed in a future.", menuItem.Panel) + logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") return FilamentPanel(ui, parentPanel) case "toolchanger": - utils.Logger.Warn("WARNING! the 'toolchanger' panel has been renamed to 'tool-changer'. Please use the 'tool-changer' panel instead.") - utils.Logger.Warnf("Support for the %s panel remains in this release, but will be removed in a future.", menuItem.Panel) - utils.Logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") + logger.Warn("WARNING! the 'toolchanger' panel has been renamed to 'tool-changer'. Please use the 'tool-changer' panel instead.") + logger.Warnf("Support for the %s panel remains in this release, but will be removed in a future.", menuItem.Panel) + logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") return ToolChangerPanel(ui, parentPanel) case "nozzle-calibration": - utils.Logger.Warn("WARNING! the 'nozzle-calibration' panel has been deprecated. Please use the 'z-offset-calibration' panel instead.") - utils.Logger.Warn("Support for the nozzle-calibration panel remains in this release, but will be removed in a future.") - utils.Logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") + logger.Warn("WARNING! the 'nozzle-calibration' panel has been deprecated. Please use the 'z-offset-calibration' panel instead.") + logger.Warn("Support for the nozzle-calibration panel remains in this release, but will be removed in a future.") + logger.Warn("Please update the custom menu structure in your OctoScreen settings in OctoPrint.") return ZOffsetCalibrationPanel(ui, parentPanel) - default: - logLevel := utils.LowerCaseLogLevel() + logLevel := logger.LogLevel() if logLevel == "debug" { - utils.Logger.Fatalf("menu.getPanel() - unknown menuItem.Panel: %q", menuItem.Panel) + logger.Fatalf("menu.getPanel() - unknown menuItem.Panel: %q", menuItem.Panel) } return nil @@ -218,7 +218,7 @@ func getDefaultMenuItems(client *octoprintApis.Client) []dataModels.MenuItem { } if err != nil { - utils.LogError("menu.getDefaultMenuItems()", "json.Unmarshal()", err) + logger.LogError("menu.getDefaultMenuItems()", "json.Unmarshal()", err) } return menuItems diff --git a/ui/tool_changer_panel.go b/ui/tool_changer_panel.go index 59bda907..dc29fcb0 100755 --- a/ui/tool_changer_panel.go +++ b/ui/tool_changer_panel.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -59,9 +60,9 @@ func (this *toolChangerPanel) createMagnetOnButton() gtk.IWidget { cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{"SET_PIN PIN=sol VALUE=1"} - utils.Logger.Info("Turn on magnet") + logger.Info("Turn on magnet") if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("tool-changer.createMagnetOnButton()", "Do(CommandRequest)", err) + logger.LogError("tool-changer.createMagnetOnButton()", "Do(CommandRequest)", err) return } }) @@ -72,9 +73,9 @@ func (this *toolChangerPanel) createMagnetOffButton() gtk.IWidget { cmd := &octoprintApis.CommandRequest{} cmd.Commands = []string{"SET_PIN PIN=sol VALUE=0"} - utils.Logger.Info("Turn off magnet") + logger.Info("Turn off magnet") if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("tool-changer.createMagnetOffButton()", "Do(CommandRequest)", err) + logger.LogError("tool-changer.createMagnetOffButton()", "Do(CommandRequest)", err) return } }) @@ -94,7 +95,7 @@ func (this *toolChangerPanel) setToolheadButtonClickHandlers(toolheadButtons []* func (this *toolChangerPanel) setToolheadButtonClickHandler(toolheadButton *gtk.Button, toolheadIndex int) { toolheadButton.Connect("clicked", func() { - utils.Logger.Infof("Changing tool to tool%d", toolheadIndex) + logger.Infof("Changing tool to tool%d", toolheadIndex) gcode := fmt.Sprintf("T%d", toolheadIndex) this.command(gcode) diff --git a/ui/ui.go b/ui/ui.go index 4542d00e..4c4b4688 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -12,6 +12,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -46,7 +47,7 @@ type UI struct { } func New(endpoint, key string, width, height int) *UI { - utils.Logger.Debug("entering ui.New()") + logger.TraceEnter("ui.New()") if width == 0 || height == 0 { width = utils.WindowWidth @@ -76,12 +77,12 @@ func New(endpoint, key string, width, height int) *UI { if (allocatedWidth > width || allocatedHeight > height) || (sizeWidth > width || sizeHeight > height) { - utils.Logger.Errorf("Widow resize went past max size. allocatedWidth:%d allocatedHeight:%d sizeWidth:%d sizeHeight:%d", + logger.Errorf("Window resize went past max size. allocatedWidth:%d allocatedHeight:%d sizeWidth:%d sizeHeight:%d", allocatedWidth, allocatedHeight, sizeWidth, sizeHeight) - utils.Logger.Errorf("Widow resize went past max size. Target width and height: %dx%d", + logger.Errorf("Window resize went past max size. Target width and height: %dx%d", width, height) } @@ -102,12 +103,12 @@ func New(endpoint, key string, width, height int) *UI { instance.backgroundTask = utils.CreateBackgroundTask(time.Second * 10, instance.update) instance.initialize() - utils.Logger.Debug("leaving ui.New()") + logger.TraceLeave("ui.New()") return instance } func (this *UI) initialize() { - utils.Logger.Debug("entering ui.initialize()") + logger.TraceEnter("ui.initialize()") defer this.window.ShowAll() this.loadStyle() @@ -118,7 +119,7 @@ func (this *UI) initialize() { this.window.Connect("show", this.backgroundTask.Start) this.window.Connect("destroy", func() { - utils.Logger.Debug("window destroy callback was called, now executing MainQuit()") + logger.Debug("window destroy callback was called, now executing MainQuit()") gtk.MainQuit() }) @@ -128,53 +129,52 @@ func (this *UI) initialize() { this.grid = utils.MustGrid() overlay.Add(this.grid) - this.sdNotify("READY=1") + this.sdNotify(daemon.SdNotifyReady) - utils.Logger.Debug("leaving ui.initialize()") + logger.TraceLeave("ui.initialize()") } func (this *UI) loadStyle() { - utils.Logger.Debug("entering ui.loadStyle()") + logger.TraceEnter("ui.loadStyle()") cssProvider := utils.MustCSSProviderFromFile(utils.CSSFilename) screenDefault, err := gdk.ScreenGetDefault() if err != nil { - utils.LogError("ui.loadStyle()", "ScreenGetDefault()", err) - - utils.Logger.Debug("leaving ui.loadStyle()") + logger.LogError("ui.loadStyle()", "ScreenGetDefault()", err) + logger.TraceLeave("ui.loadStyle()") return } gtk.AddProviderForScreen(screenDefault, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER) - utils.Logger.Debug("leaving ui.loadStyle()") + logger.TraceLeave("ui.loadStyle()") } var errMercyPeriod = time.Second * 10 func (this *UI) verifyConnection() { - utils.Logger.Debug("entering ui.verifyConnection()") + logger.TraceEnter("ui.verifyConnection()") - this.sdNotify("WATCHDOG=1") + this.sdNotify(daemon.SdNotifyWatchdog) newUIState := "<>" splashMessage := "<>" connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client) if err == nil { - utils.Logger.Debug("ui.verifyConnection() - ConnectionRequest.Do() succeeded") + logger.Debug("ui.verifyConnection() - ConnectionRequest.Do() succeeded") jsonResponse, err := utils.StructToJson(connectionResponse) if err != nil { - utils.Logger.Debug("ui.verifyConnection() - utils.StructToJson() failed") + logger.Debug("ui.verifyConnection() - utils.StructToJson() failed") } else { - utils.Logger.Debugf("ui.verifyConnection() - connectionResponse is: %s", jsonResponse) + logger.Debugf("ui.verifyConnection() - connectionResponse is: %s", jsonResponse) } this.ConnectionState = connectionResponse.Current.State newUIState, splashMessage = this.getUiStateAndMessageFromConnectionResponse(connectionResponse, newUIState, splashMessage) } else { - utils.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err) + logger.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err) newUIState, splashMessage = this.getUiStateAndMessageFromError(err, newUIState, splashMessage) } @@ -184,7 +184,7 @@ func (this *UI) verifyConnection() { this.setUiState(newUIState, splashMessage) }() - utils.Logger.Debug("leaving ui.verifyConnection()") + logger.TraceLeave("ui.verifyConnection()") } @@ -193,54 +193,53 @@ func (this *UI) getUiStateAndMessageFromConnectionResponse( newUIState string, splashMessage string, ) (string, string) { - utils.Logger.Debug("entering ui.getUiStateAndMessageFromConnectionResponse()") + logger.TraceEnter("ui.getUiStateAndMessageFromConnectionResponse()") strCurrentState := string(connectionResponse.Current.State) - utils.Logger.Debugf("ui.getUiStateAndMessageFromConnectionResponse() - strCurrentState is %s", strCurrentState) + logger.Debugf("ui.getUiStateAndMessageFromConnectionResponse() - strCurrentState is %s", strCurrentState) switch { case connectionResponse.Current.State.IsOperational(): - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is idle") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is idle") newUIState = "idle" splashMessage = "Initializing..." case connectionResponse.Current.State.IsPrinting(): - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is printing") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is printing") newUIState = "printing" splashMessage = "Printing..." case connectionResponse.Current.State.IsError(): - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state has an error") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state has an error") fallthrough case connectionResponse.Current.State.IsOffline(): - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state is now offline and displaying the splash panel") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state is now offline and displaying the splash panel") newUIState = "splash" - utils.Logger.Info("ui.getUiStateAndMessageFromConnectionResponse() - new UI state is 'splash' and is about to call ConnectRequest.Do()") + logger.Info("ui.getUiStateAndMessageFromConnectionResponse() - new UI state is 'splash' and is about to call ConnectRequest.Do()") if err := (&octoprintApis.ConnectRequest{}).Do(this.Client); err != nil { - utils.LogError("ui.getUiStateAndMessageFromConnectionResponse()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) + logger.LogError("ui.getUiStateAndMessageFromConnectionResponse()", "s.Current.State is IsOffline, and (ConnectRequest)Do(UI.Client)", err) splashMessage = "Loading..." } else { splashMessage = "Printer is offline, now trying to connect..." } case connectionResponse.Current.State.IsConnecting(): - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is splash (from IsConnecting)") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is splash (from IsConnecting)") newUIState = "splash" splashMessage = strCurrentState default: - utils.Logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the default case was hit") + logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the default case was hit") switch strCurrentState { case "Cancelling": newUIState = "idle" default: - utils.Logger.Errorf("ui.getUiStateAndMessageFromConnectionResponse() - unknown CurrentState: %q", strCurrentState) + logger.Errorf("ui.getUiStateAndMessageFromConnectionResponse() - unknown CurrentState: %q", strCurrentState) } } - utils.Logger.Debug("leaving ui.getUiStateAndMessageFromConnectionResponse()") - + logger.TraceLeave("ui.getUiStateAndMessageFromConnectionResponse()") return newUIState, splashMessage } @@ -250,16 +249,16 @@ func (this *UI) getUiStateAndMessageFromError( newUIState string, splashMessage string, ) (string, string) { - utils.Logger.Debug("entering ui.getUiStateAndMessageFromError()") + logger.TraceEnter("ui.getUiStateAndMessageFromError()") - utils.Logger.Info("ui.getUiStateAndMessageFromError() - now setting newUIState to 'splash'") + logger.Info("ui.getUiStateAndMessageFromError() - now setting newUIState to 'splash'") newUIState = "splash" if time.Since(this.time) > errMercyPeriod { errMessage := this.errToUser(err) - utils.Logger.Info("ui.getUiStateAndMessageFromError() - printer is offline") - utils.Logger.Infof("ui.getUiStateAndMessageFromError() - errMessage is: %q", errMessage) + logger.Info("ui.getUiStateAndMessageFromError() - printer is offline") + logger.Infof("ui.getUiStateAndMessageFromError() - errMessage is: %q", errMessage) if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") { splashMessage = "Printer is offline (deadline exceeded), retrying to connect..." @@ -274,8 +273,7 @@ func (this *UI) getUiStateAndMessageFromError( splashMessage = "Printer is offline! (retrying to connect...)" } - utils.Logger.Debug("leaving ui.getUiStateAndMessageFromError()") - + logger.TraceLeave("ui.getUiStateAndMessageFromError()") return newUIState, splashMessage } @@ -284,54 +282,54 @@ func (this *UI) setUiState( newUiState string, splashMessage string, ) { - utils.Logger.Debug("entering ui.setUiState()") + logger.TraceEnter("ui.setUiState()") this.splashPanel.Label.SetText(splashMessage) if newUiState == this.UIState { - utils.Logger.Infof("ui.setUiState() - newUiState and ui.UIState are the same (%q)", this.UIState) - utils.Logger.Debug("leaving ui.setUiState()") + logger.Infof("ui.setUiState() - newUiState and ui.UIState are the same (%q)", this.UIState) + logger.TraceLeave("ui.setUiState()") return } - utils.Logger.Info("ui.setUiState() - newUiState does not equal ui.UIState") - utils.Logger.Infof("ui.setUiState() - ui.UIState is: %q", this.UIState) - utils.Logger.Infof("ui.setUiState() - newUiState is: %q", newUiState) + logger.Info("ui.setUiState() - newUiState does not equal ui.UIState") + logger.Infof("ui.setUiState() - ui.UIState is: %q", this.UIState) + logger.Infof("ui.setUiState() - newUiState is: %q", newUiState) this.UIState = newUiState switch newUiState { case "idle": - utils.Logger.Info("ui.setUiState() - printer is ready") + logger.Info("ui.setUiState() - printer is ready") this.GoToPanel(IdleStatusPanel(this)) case "printing": - utils.Logger.Info("ui.setUiState() - printing a job") + logger.Info("ui.setUiState() - printing a job") this.GoToPanel(PrintStatusPanel(this)) case "splash": this.GoToPanel(this.splashPanel) default: - utils.Logger.Errorf("ERROR: ui.setUiState() - unknown newUiState case: %q", newUiState) + logger.Errorf("ERROR: ui.setUiState() - unknown newUiState case: %q", newUiState) } - utils.Logger.Debug("leaving ui.setUiState()") + logger.TraceLeave("ui.setUiState()") } func (this *UI) checkNotification() { - utils.Logger.Debug("entering ui.checkNotification()") + logger.TraceEnter("ui.checkNotification()") if !this.OctoPrintPluginIsAvailable { - utils.Logger.Info("ui.checkNotification() - OctoPrintPluginIsAvailable is false, so not calling GetNotification") - utils.Logger.Debug("leaving ui.checkNotification()") + logger.Info("ui.checkNotification() - OctoPrintPluginIsAvailable is false, so not calling GetNotification") + logger.TraceLeave("ui.checkNotification()") return } notificationResponse, err := (&octoprintApis.NotificationRequest{}).Do(this.Client, this.UIState) if err != nil { - utils.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) - utils.Logger.Debug("leaving ui.checkNotification()") + logger.LogError("ui.checkNotification()", "Do(GetNotificationRequest)", err) + logger.TraceLeave("ui.checkNotification()") return } @@ -339,11 +337,11 @@ func (this *UI) checkNotification() { utils.InfoMessageDialogBox(this.window, notificationResponse.Message) } - utils.Logger.Debug("leaving ui.checkNotification()") + logger.TraceLeave("ui.checkNotification()") } func (this *UI) loadSettings() { - utils.Logger.Debug("entering ui.loadSettings()") + logger.TraceEnter("ui.loadSettings()") settingsResponse, err := (&octoprintApis.OctoScreenSettingsRequest{}).Do(this.Client, this.UIState) if err != nil { @@ -353,16 +351,16 @@ func (this *UI) loadSettings() { // OctoScreen plug-in is available. If calling GetSettings returns // a 404, the plug-in isn't available. this.OctoPrintPluginIsAvailable = false - utils.Logger.Info("The OctoScreen plug-in is not available") + logger.Info("The OctoScreen plug-in is not available") } else { // If we get back any other kind of error, something bad happened, so log an error. - utils.LogError("ui.loadSettings()", "Do(GetSettingsRequest)", err) + logger.LogError("ui.loadSettings()", "Do(GetSettingsRequest)", err) } - utils.Logger.Debug("leaving ui.loadSettings()") + logger.TraceLeave("ui.loadSettings()") return } else { - utils.Logger.Info("The call to GetSettings succeeded and the OctoPrint plug-in is available") + logger.Info("The call to GetSettings succeeded and the OctoPrint plug-in is available") } if !this.validateMenuItems(settingsResponse.MenuStructure, "", true) { @@ -371,11 +369,14 @@ func (this *UI) loadSettings() { this.Settings = settingsResponse - utils.Logger.Debug("leaving ui.loadSettings()") + logger.TraceLeave("ui.loadSettings()") } func (this *UI) validateMenuItems(menuItems []dataModels.MenuItem, name string, isRoot bool) bool { + logger.TraceEnter("ui.validateMenuItems()") + if menuItems == nil { + logger.TraceLeave("ui.validateMenuItems()") return true } @@ -402,6 +403,7 @@ func (this *UI) validateMenuItems(menuItems []dataModels.MenuItem, name string, ) fatalErrorWindow.ShowAll() + logger.TraceLeave("ui.validateMenuItems()") return false } @@ -409,26 +411,29 @@ func (this *UI) validateMenuItems(menuItems []dataModels.MenuItem, name string, menuItem := menuItems[i] if menuItem.Panel == "menu" { if !this.validateMenuItems(menuItem.Items, menuItem.Name, false) { + logger.TraceLeave("ui.validateMenuItems()") return false } } } + logger.TraceLeave("ui.validateMenuItems()") return true } func (this *UI) update() { - utils.Logger.Debug("entering ui.update()") + logger.TraceEnter("ui.update()") if this.connectionAttempts > 8 { + logger.Info("ui.update() - this.connectionAttempts > 8") this.splashPanel.putOnHold() - this.sdNotify("WATCHDOG=1") + this.sdNotify(daemon.SdNotifyWatchdog) - utils.Logger.Debug("leaving ui.update() - connectionAttempts > 8") + logger.TraceLeave("ui.update()") return } - utils.Logger.Infof("ui.update() - this.UIState is: %q", this.UIState) + logger.Infof("ui.update() - this.UIState is: %q", this.UIState) if this.UIState == "splash" { this.connectionAttempts++ @@ -458,44 +463,42 @@ func (this *UI) update() { this.verifyConnection() - utils.Logger.Debug("leaving ui.update()") + logger.TraceLeave("ui.update()") } func (this *UI) sdNotify(state string) { - utils.Logger.Debug("entering ui.sdNotify()") + logger.TraceEnter("ui.sdNotify()") _, err := daemon.SdNotify(false, state) if err != nil { - utils.Logger.Errorf("ui.sdNotify()", "SdNotify()", err) + logger.Errorf("ui.sdNotify()", "SdNotify()", err) } - utils.Logger.Debug("leaving ui.sdNotify()") + logger.TraceLeave("ui.sdNotify()") } func (this *UI) GoToPanel(panel interfaces.IPanel) { - utils.Logger.Debug("entering ui.GoToPanel()") + logger.TraceEnter("ui.GoToPanel()") this.SetUiToPanel(panel) this.PanelHistory.Push(panel) - utils.Logger.Debug("leaving ui.GoToPanel()") + logger.TraceLeave("ui.GoToPanel()") } func (this *UI) GoToPreviousPanel() { - utils.Logger.Debug("entering ui.GoToPreviousPanel()") + logger.TraceEnter("ui.GoToPreviousPanel()") stackLength := this.PanelHistory.Len() if stackLength < 2 { - utils.Logger.Error("ui.GoToPreviousPanel() - stack does not contain current panel and parent panel") - - utils.Logger.Debug("leaving ui.GoToPreviousPanel()") + logger.Error("ui.GoToPreviousPanel() - stack does not contain current panel and parent panel") + logger.TraceLeave("ui.GoToPreviousPanel()") return } if stackLength < 1 { - utils.Logger.Error("ui.GoToPreviousPanel() - GoToPreviousPanel() was called but the stack is empty") - - utils.Logger.Debug("leaving ui.GoToPreviousPanel()") + logger.Error("ui.GoToPreviousPanel() - GoToPreviousPanel() was called but the stack is empty") + logger.TraceLeave("ui.GoToPreviousPanel()") return } @@ -505,11 +508,11 @@ func (this *UI) GoToPreviousPanel() { parentPanel := this.PanelHistory.Peek().(interfaces.IPanel) this.SetUiToPanel(parentPanel) - utils.Logger.Debug("leaving ui.GoToPreviousPanel()") + logger.TraceLeave("ui.GoToPreviousPanel()") } func (this *UI) SetUiToPanel(panel interfaces.IPanel) { - utils.Logger.Debug("entering ui.SetUiToPanel()") + logger.TraceEnter("ui.SetUiToPanel()") stackLength := this.PanelHistory.Len() if stackLength > 0 { @@ -522,34 +525,34 @@ func (this *UI) SetUiToPanel(panel interfaces.IPanel) { this.grid.Attach(panel.Grid(), 0, 0, 1, 1) this.grid.ShowAll() - utils.Logger.Debug("leaving ui.SetUiToPanel()") + logger.TraceLeave("ui.SetUiToPanel()") } func (this *UI) RemovePanelFromUi(panel interfaces.IPanel) { - utils.Logger.Debug("entering ui.RemovePanelFromUi()") + logger.TraceEnter("ui.RemovePanelFromUi()") defer panel.Hide() this.grid.Remove(panel.Grid()) - utils.Logger.Debug("leaving ui.RemovePanelFromUi()") + logger.TraceLeave("ui.RemovePanelFromUi()") } func (this *UI) errToUser(err error) string { - utils.Logger.Debug("entering ui.errToUser()") + logger.TraceEnter("ui.errToUser()") text := strings.ToLower(err.Error()) if strings.Contains(text, "connection refused") { - utils.Logger.Debug("leaving ui.errToUser() - connection refused") + logger.TraceLeave("ui.errToUser() - connection refused") return "Unable to connect to OctoPrint, check if it running." } else if strings.Contains(text, "request canceled") { - utils.Logger.Debug("leaving ui.errToUser() - request canceled") + logger.TraceLeave("ui.errToUser() - request canceled") return "Loading..." } else if strings.Contains(text, "connection broken") { - utils.Logger.Debug("leaving ui.errToUser() - connection broken") + logger.TraceLeave("ui.errToUser() - connection broken") return "Loading..." } - utils.Logger.Debugf("leaving ui.errToUser() - unexpected error: %q", text) - + msg := fmt.Sprintf("ui.errToUser() - unexpected error: %s", text) + logger.TraceLeave(msg) return fmt.Sprintf("Unexpected Error: %s", text) } diff --git a/ui/z_offset_calibration_panel.go b/ui/z_offset_calibration_panel.go index c4e2a595..e0ab17c6 100755 --- a/ui/z_offset_calibration_panel.go +++ b/ui/z_offset_calibration_panel.go @@ -7,6 +7,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -92,7 +93,7 @@ func (this *zOffsetCalibrationPanel) CreateSelectToolStepButton() { this.selectHotendStepButton = uiWidgets.CreateSelectHotendStepButton(this.UI.Client, false) _, err := this.selectHotendStepButton.Connect("clicked", this.selectToolStepButtonHandleClick) if err != nil { - utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateSelectToolStepButton()", "selectHotendStepButton.Connect()", err) + logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateSelectToolStepButton()", "selectHotendStepButton.Connect()", err) panic(err) } @@ -105,7 +106,7 @@ func (this *zOffsetCalibrationPanel) CreateSelectToolStepButton() { func (this *zOffsetCalibrationPanel) selectToolStepButtonHandleClick() { toolheadIndex := this.selectHotendStepButton.Index() - utils.Logger.Infof("Changing tool to tool%d", toolheadIndex) + logger.Infof("Changing tool to tool%d", toolheadIndex) gcode := fmt.Sprintf("T%d", toolheadIndex) @@ -119,7 +120,7 @@ func (this *zOffsetCalibrationPanel) selectToolStepButtonHandleClick() { cmd := &octoprintApis.ZOffsetRequest{Tool: this.activeTool} response, err := cmd.Do(this.UI.Client) if err != nil { - utils.LogError("z_offset_calibration.setToolheadButtonClickHandler()", "Do(GetZOffsetRequest)", err) + logger.LogError("z_offset_calibration.setToolheadButtonClickHandler()", "Do(GetZOffsetRequest)", err) return } @@ -133,7 +134,7 @@ func (this *zOffsetCalibrationPanel) CreateDecreaseZOffsetButton() { this.decreaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(false) _, err := this.decreaseZOffsetButton.Connect("clicked", this.decreaseZOffsetButtonClicked) if err != nil { - utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateDecreaseZOffsetButton()", "decreaseZOffsetButton.Connect()", err) + logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateDecreaseZOffsetButton()", "decreaseZOffsetButton.Connect()", err) panic(err) } this.Grid().Attach(this.decreaseZOffsetButton, 1, 0, 1, 1) @@ -151,7 +152,7 @@ func (this *zOffsetCalibrationPanel) CreateIncreaseZOffsetButton() { this.increaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(true) _, err := this.increaseZOffsetButton.Connect("clicked", this.increaseZOffsetButtonClicked) if err != nil { - utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateIncreaseZOffsetButton()", "increaseZOffsetButton.Connect()", err) + logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateIncreaseZOffsetButton()", "increaseZOffsetButton.Connect()", err) panic(err) } this.Grid().Attach(this.increaseZOffsetButton, 2, 0, 1, 1) @@ -185,7 +186,7 @@ func (this *zOffsetCalibrationPanel) CreateManualZCalibrationStepButton() { this.manualZCalibrationStepButton = uiWidgets.CreateManualZCalibrationStepButton() _, err := this.manualZCalibrationStepButton.Connect("clicked", this.manualZCalibrationStepButtonHandleClick) if err != nil { - utils.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateManualZCalibrationStepButton()", "manualZCalibrationStepButton.Connect()", err) + logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateManualZCalibrationStepButton()", "manualZCalibrationStepButton.Connect()", err) panic(err) } @@ -221,7 +222,7 @@ func (this *zOffsetCalibrationPanel) CreateAutoZCalibrationButton() gtk.IWidget // when RunZOffsetCalibrationRequest is called, it's returning a 404. cmd := &octoprintApis.RunZOffsetCalibrationRequest{} if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("z_offset_calibration.createAutoZCalibrationButton()", "Do(RunZOffsetCalibrationRequest)", err) + logger.LogError("z_offset_calibration.createAutoZCalibrationButton()", "Do(RunZOffsetCalibrationRequest)", err) } }) } @@ -239,7 +240,7 @@ func (this *zOffsetCalibrationPanel) updateZOffset(value float64) { "G0 Z0 F100", } if err := cmd.Do(this.UI.Client); err != nil { - utils.LogError("z_offset_calibration.updateZOffset()", "Do(CommandRequest)", err) + logger.LogError("z_offset_calibration.updateZOffset()", "Do(CommandRequest)", err) } cmd2 := &octoprintApis.SetZOffsetRequest { @@ -247,7 +248,7 @@ func (this *zOffsetCalibrationPanel) updateZOffset(value float64) { Tool: this.activeTool, } if err := cmd2.Do(this.UI.Client); err != nil { - utils.LogError("z_offset_calibration.updateZOffset()", "Do(SetZOffsetRequest)", err) + logger.LogError("z_offset_calibration.updateZOffset()", "Do(SetZOffsetRequest)", err) } } diff --git a/uiWidgets/AmountToExtrudeStepButton.go b/uiWidgets/AmountToExtrudeStepButton.go index c84a6b7e..08baafb0 100755 --- a/uiWidgets/AmountToExtrudeStepButton.go +++ b/uiWidgets/AmountToExtrudeStepButton.go @@ -1,7 +1,7 @@ package uiWidgets import ( - "github.com/Z-Bolt/OctoScreen/utils" + "github.com/Z-Bolt/OctoScreen/logger" ) type AmountToExtrudeStepButton struct { @@ -19,7 +19,7 @@ func CreateAmountToExtrudeStepButton() *AmountToExtrudeStepButton { Step{" 10mm", "move-step.svg", nil, 10}, ) if err != nil { - utils.LogError("PANIC!!! - CreateAmountToExtrudeStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateAmountToExtrudeStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/AmountToMoveStepButton.go b/uiWidgets/AmountToMoveStepButton.go index 42b1d636..38430dfe 100755 --- a/uiWidgets/AmountToMoveStepButton.go +++ b/uiWidgets/AmountToMoveStepButton.go @@ -1,7 +1,7 @@ package uiWidgets import ( - "github.com/Z-Bolt/OctoScreen/utils" + "github.com/Z-Bolt/OctoScreen/logger" ) type AmountToMoveStepButton struct { @@ -19,7 +19,7 @@ func CreateAmountToMoveStepButton() *AmountToMoveStepButton { Step{" 1mm", "move-step.svg", nil, 1.00}, ) if err != nil { - utils.LogError("PANIC!!! - CreateAmountToMoveStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateAmountToMoveStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index 1488a1dc..0a1e4282 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -4,6 +4,7 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -32,7 +33,7 @@ func CreateCommandButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateCommandButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateCommandButton()", "instance.Button.Connect()", err) panic(err) } @@ -56,6 +57,6 @@ func (this *CommandButton) sendCommand() { err := commandRequest.Do(this.client) if err != nil { - utils.LogError("CommandButton.sendCommand()", "Do(SystemExecuteCommandRequest)", err) + logger.LogError("CommandButton.sendCommand()", "Do(SystemExecuteCommandRequest)", err) } } diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index aa6b8231..a8cd86af 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -4,6 +4,7 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -32,7 +33,7 @@ func CreateControlButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateControlButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateControlButton()", "instance.Button.Connect()", err) panic(err) } @@ -57,9 +58,9 @@ func (this *ControlButton) sendCommand() { commandRequest.Commands = []string{this.controlDefinition.Command} } - utils.Logger.Infof("Executing command %q", this.controlDefinition.Name) + logger.Infof("Executing command %q", this.controlDefinition.Name) err := commandRequest.Do(this.client) if err != nil { - utils.LogError("ControlButton.sendCommand()", "Do(CommandRequest)", err) + logger.LogError("ControlButton.sendCommand()", "Do(CommandRequest)", err) } } diff --git a/uiWidgets/CoolDownButton.go b/uiWidgets/CoolDownButton.go index 59c4f413..8f00e54b 100755 --- a/uiWidgets/CoolDownButton.go +++ b/uiWidgets/CoolDownButton.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -29,7 +30,7 @@ func CreateCoolDownButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateCoolDownButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateCoolDownButton()", "instance.Button.Connect()", err) panic(err) } @@ -53,7 +54,7 @@ func TurnAllHeatersOff( } err := bedTargetRequest.Do(client) if err != nil { - utils.LogError("CoolDownButton.handleClicked()", "Do(BedTargetRequest)", err) + logger.LogError("CoolDownButton.handleClicked()", "Do(BedTargetRequest)", err) return } @@ -67,7 +68,7 @@ func TurnAllHeatersOff( } err = toolTargetRequest.Do(client) if err != nil { - utils.LogError("TemperaturePresetsPanel.setTemperaturesToPreset()", "Do(ToolTargetRequest)", err) + logger.LogError("TemperaturePresetsPanel.setTemperaturesToPreset()", "Do(ToolTargetRequest)", err) } } } diff --git a/uiWidgets/FanButton.go b/uiWidgets/FanButton.go index dd7f3e4f..ad5de56d 100755 --- a/uiWidgets/FanButton.go +++ b/uiWidgets/FanButton.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -41,7 +42,7 @@ func CreateFanButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateFanButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateFanButton()", "instance.Button.Connect()", err) panic(err) } @@ -56,6 +57,6 @@ func (this *FanButton) handleClicked() { err := cmd.Do(this.client) if err != nil { - utils.LogError("FanButton.handleClicked()", "Do(CommandRequest)", err) + logger.LogError("FanButton.handleClicked()", "Do(CommandRequest)", err) } } diff --git a/uiWidgets/FilamentExtrudeButton.go b/uiWidgets/FilamentExtrudeButton.go index 01af4896..858a702e 100755 --- a/uiWidgets/FilamentExtrudeButton.go +++ b/uiWidgets/FilamentExtrudeButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -44,7 +45,7 @@ func CreateFilamentExtrudeButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateFilamentExtrudeButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateFilamentExtrudeButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FilamentLoadButton.go b/uiWidgets/FilamentLoadButton.go index 1d46e83e..79dfb2cd 100755 --- a/uiWidgets/FilamentLoadButton.go +++ b/uiWidgets/FilamentLoadButton.go @@ -4,6 +4,7 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -47,7 +48,7 @@ func CreateFilamentLoadButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateFilamentLoadButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateFilamentLoadButton()", "instance.Button.Connect()", err) panic(err) } diff --git a/uiWidgets/FlowRateStepButton.go b/uiWidgets/FlowRateStepButton.go index 3144d31f..c665875d 100755 --- a/uiWidgets/FlowRateStepButton.go +++ b/uiWidgets/FlowRateStepButton.go @@ -1,6 +1,7 @@ package uiWidgets import ( + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -21,7 +22,7 @@ func CreateFlowRateStepButton( Step{"Slow (75%)", "speed-slow.svg", nil, 75}, ) if err != nil { - utils.LogError("PANIC!!! - CreateFlowRateStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateFlowRateStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/HomeAllButton.go b/uiWidgets/HomeAllButton.go index 630580a0..b36f8489 100755 --- a/uiWidgets/HomeAllButton.go +++ b/uiWidgets/HomeAllButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -24,7 +25,7 @@ func CreateHomeAllButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateHomeAllButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateHomeAllButton()", "instance.Button.Connect()", err) panic(err) } @@ -32,7 +33,7 @@ func CreateHomeAllButton( } func (this *HomeAllButton) handleClicked() { - utils.Logger.Infof("Homing the print head") + logger.Infof("Homing the print head") // Version A: axes := []dataModels.Axis { @@ -43,7 +44,7 @@ func (this *HomeAllButton) handleClicked() { cmd := &octoprintApis.PrintHeadHomeRequest{Axes: axes} err := cmd.Do(this.client); if err != nil { - utils.LogError("HomeAllButton.handleClicked()", "Do(PrintHeadHomeRequest)", err) + logger.LogError("HomeAllButton.handleClicked()", "Do(PrintHeadHomeRequest)", err) } @@ -57,7 +58,7 @@ func (this *HomeAllButton) handleClicked() { } if err := cmd.Do(m.UI.Client); err != nil { - utils.LogError("HomeAllButton.handleClicked()", "Do(CommandRequest)", err) + logger.LogError("HomeAllButton.handleClicked()", "Do(CommandRequest)", err) } */ } diff --git a/uiWidgets/HomeButton.go b/uiWidgets/HomeButton.go index 09ba202b..5733798b 100755 --- a/uiWidgets/HomeButton.go +++ b/uiWidgets/HomeButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -29,7 +30,7 @@ func CreateHomeButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateHomeButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateHomeButton()", "instance.Button.Connect()", err) panic(err) } @@ -38,9 +39,9 @@ func CreateHomeButton( func (this *HomeButton) handleClicked() { cmd := &octoprintApis.PrintHeadHomeRequest{Axes: this.axes} - utils.Logger.Infof("Homing the print head in %s axes", this.axes) + logger.Infof("Homing the print head in %s axes", this.axes) err := cmd.Do(this.client); if err != nil { - utils.LogError("HomeButton.handleClicked()", "Do(PrintHeadHomeRequest)", err) + logger.LogError("HomeButton.handleClicked()", "Do(PrintHeadHomeRequest)", err) } } diff --git a/uiWidgets/ManualZCalibrationStepButton.go b/uiWidgets/ManualZCalibrationStepButton.go index 833657f0..b9b6614f 100755 --- a/uiWidgets/ManualZCalibrationStepButton.go +++ b/uiWidgets/ManualZCalibrationStepButton.go @@ -1,7 +1,7 @@ package uiWidgets import ( - "github.com/Z-Bolt/OctoScreen/utils" + "github.com/Z-Bolt/OctoScreen/logger" ) type ManualZCalibrationStepButton struct { @@ -15,7 +15,7 @@ func CreateManualZCalibrationStepButton() *ManualZCalibrationStepButton { Step{"Stop Manual\nZ Calibration", "z-calibration.svg", nil, true}, ) if err != nil { - utils.LogError("PANIC!!! - CreateManualZCalibrationStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateManualZCalibrationStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/MoveButton.go b/uiWidgets/MoveButton.go index 84475978..7eb4a4d1 100755 --- a/uiWidgets/MoveButton.go +++ b/uiWidgets/MoveButton.go @@ -2,9 +2,9 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" - "github.com/Z-Bolt/OctoScreen/utils" ) type MoveButton struct { @@ -55,7 +55,7 @@ func (this *MoveButton) handlePressed() { } if err := cmd.Do(this.client); err != nil { - utils.LogError("MoveButton.handlePressed()", "Do(PrintHeadJogRequest)", err) + logger.LogError("MoveButton.handlePressed()", "Do(PrintHeadJogRequest)", err) return } } diff --git a/uiWidgets/MustPressedButton.go b/uiWidgets/MustPressedButton.go index 88dee82f..db04721e 100755 --- a/uiWidgets/MustPressedButton.go +++ b/uiWidgets/MustPressedButton.go @@ -5,6 +5,7 @@ import ( "time" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -20,7 +21,7 @@ func MustPressedButton( button, err := gtk.ButtonNewWithLabel(label) if err != nil { - utils.LogError("PANIC!!! - MustPressedButton()", "gtk.ButtonNewWithLabel()", err) + logger.LogError("PANIC!!! - MustPressedButton()", "gtk.ButtonNewWithLabel()", err) panic(err) } diff --git a/uiWidgets/OctoPrintInfoBox.go b/uiWidgets/OctoPrintInfoBox.go index 68f7395a..dd82a82d 100755 --- a/uiWidgets/OctoPrintInfoBox.go +++ b/uiWidgets/OctoPrintInfoBox.go @@ -2,8 +2,8 @@ package uiWidgets import ( "fmt" - // "log" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -25,7 +25,7 @@ func CreateOctoPrintInfoBox( apiVersion := "" versionResponse, err := (&octoprintApis.VersionRequest{}).Do(client) if err != nil { - utils.LogError("OctoPrintInfoBox.CreateOctoPrintInfoBox()", "VersionRequest.Do()", err) + logger.LogError("OctoPrintInfoBox.CreateOctoPrintInfoBox()", "VersionRequest.Do()", err) } else if versionResponse == nil { server = "Unknown?" apiVersion = "Unknown?" diff --git a/uiWidgets/OctoScreenPluginInfoBox.go b/uiWidgets/OctoScreenPluginInfoBox.go index 1ea8389e..8cf1ce5e 100755 --- a/uiWidgets/OctoScreenPluginInfoBox.go +++ b/uiWidgets/OctoScreenPluginInfoBox.go @@ -3,6 +3,7 @@ package uiWidgets import ( // "fmt" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -24,7 +25,7 @@ func CreateOctoScreenPluginInfoBox( if octoPrintPluginIsInstalled { pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client, uiState) if err != nil { - utils.LogError("CreateOctoScreenPluginInfoBox()", "PluginManagerInfoRequest.Do()", err) + logger.LogError("CreateOctoScreenPluginInfoBox()", "PluginManagerInfoRequest.Do()", err) str2 = "Error" } else { found := false diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index acd2964a..be5a1754 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -51,7 +52,7 @@ func CreateSelectExtruderStepButton( steps..., ) if err != nil { - utils.LogError("PANIC!!! - CreateSelectExtruderStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateSelectExtruderStepButton()", "CreateStepButton()", err) panic(err) } @@ -99,7 +100,7 @@ func CreateSelectHotendStepButton( steps..., ) if err != nil { - utils.LogError("PANIC!!! - CreateSelectHotendStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateSelectHotendStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/StepButton.go b/uiWidgets/StepButton.go index 9750c5ce..ca20ab3a 100755 --- a/uiWidgets/StepButton.go +++ b/uiWidgets/StepButton.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -26,7 +27,7 @@ type StepButton struct { func CreateStepButton(colorVariation int, steps ...Step) (*StepButton, error) { if len(steps) < 1 { - utils.Logger.Error("PANIC!!! - CreateStepButton() - len(steps) < 1") + logger.Error("PANIC!!! - CreateStepButton() - len(steps) < 1") panic("StepButton.CreateStepButton() - steps is empty") } diff --git a/uiWidgets/SystemCommandButton.go b/uiWidgets/SystemCommandButton.go index 0a0fd900..134a5d37 100755 --- a/uiWidgets/SystemCommandButton.go +++ b/uiWidgets/SystemCommandButton.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -22,7 +23,7 @@ func CreateSystemCommandButton( ) *SystemCommandButton { systemCommandsResponse, err := (&octoprintApis.SystemCommandsRequest{}).Do(client) if err != nil { - utils.LogError("PANIC!!! - CreateSystemCommandButton()", "SystemCommandsRequest.Do()", err) + logger.LogError("PANIC!!! - CreateSystemCommandButton()", "SystemCommandsRequest.Do()", err) panic(err) } @@ -43,7 +44,7 @@ func CreateSystemCommandButton( } if err := systemExecuteCommandRequest.Do(client); err != nil { - utils.LogError("system.createCommandButton()", "Do(SystemExecuteCommandRequest)", err) + logger.LogError("system.createCommandButton()", "Do(SystemExecuteCommandRequest)", err) return } } diff --git a/uiWidgets/SystemInfoBox.go b/uiWidgets/SystemInfoBox.go index 3445370d..244cd49b 100755 --- a/uiWidgets/SystemInfoBox.go +++ b/uiWidgets/SystemInfoBox.go @@ -4,6 +4,7 @@ import ( // "fmt" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -41,7 +42,7 @@ func CreateSystemInfoBox( ctx.AddClass("font-size-18") base.Add(label2) - logLevel := utils.LowerCaseLogLevel() + logLevel := logger.LogLevel() if logLevel == "debug" { label3 := utils.MustLabel(str3) ctx, _ = label3.GetStyleContext() diff --git a/uiWidgets/SystemInformationInfoBox.go b/uiWidgets/SystemInformationInfoBox.go index 60687aa6..802d2c22 100755 --- a/uiWidgets/SystemInformationInfoBox.go +++ b/uiWidgets/SystemInformationInfoBox.go @@ -8,6 +8,7 @@ import ( "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" "github.com/shirou/gopsutil/mem" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/utils" ) @@ -41,7 +42,7 @@ func CreateSystemInformationInfoBox( instance := &SystemInformationInfoBox { Box: base, parentWindow: parentWindow, - logLevel: utils.LowerCaseLogLevel(), + logLevel: logger.LogLevel(), uiScaleFactor: uiScaleFactor, memoryLabel: createStyledLabel(), // loadAverageLabel: createStyledLabel(), diff --git a/uiWidgets/TemperatureAmountStepButton.go b/uiWidgets/TemperatureAmountStepButton.go index 69633934..d75f1c3c 100755 --- a/uiWidgets/TemperatureAmountStepButton.go +++ b/uiWidgets/TemperatureAmountStepButton.go @@ -1,7 +1,7 @@ package uiWidgets import ( - "github.com/Z-Bolt/OctoScreen/utils" + "github.com/Z-Bolt/OctoScreen/logger" ) type TemperatureAmountStepButton struct { @@ -18,7 +18,7 @@ func CreateTemperatureAmountStepButton() *TemperatureAmountStepButton { Step{" 5°C", "move-step.svg", nil, 5.0}, ) if err != nil { - utils.LogError("PANIC!!! - CreateTemperatureAmountStepButton()", "CreateStepButton()", err) + logger.LogError("PANIC!!! - CreateTemperatureAmountStepButton()", "CreateStepButton()", err) panic(err) } diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go index 673eef7d..ba4a1a42 100755 --- a/uiWidgets/TemperatureIncreaseButton.go +++ b/uiWidgets/TemperatureIncreaseButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -38,7 +39,7 @@ func CreateTemperatureIncreaseButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateTemperatureIncreaseButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateTemperatureIncreaseButton()", "instance.Button.Connect()", err) panic(err) } @@ -50,7 +51,7 @@ func (this *TemperatureIncreaseButton) handleClicked() { tool := this.selectHotendStepButton.Value() target, err := utils.GetToolTarget(this.client, tool) if err != nil { - utils.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err) + logger.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err) return } @@ -67,10 +68,10 @@ func (this *TemperatureIncreaseButton) handleClicked() { // TODO: should the target be checked for a max temp? // If so, how to calculate what the max should be? - utils.Logger.Infof("TemperatureIncreaseButton.handleClicked() - setting target temperature for %s to %1.f°C.", tool, target) + logger.Infof("TemperatureIncreaseButton.handleClicked() - setting target temperature for %s to %1.f°C.", tool, target) err = utils.SetToolTarget(this.client, tool, target) if err != nil { - utils.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err) + logger.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err) } } diff --git a/uiWidgets/TemperaturePresetButton.go b/uiWidgets/TemperaturePresetButton.go index 03f1eb09..c59ed3d7 100755 --- a/uiWidgets/TemperaturePresetButton.go +++ b/uiWidgets/TemperaturePresetButton.go @@ -2,6 +2,7 @@ package uiWidgets import ( "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -37,7 +38,7 @@ func CreateTemperaturePresetButton( } _, err := instance.Button.Connect("clicked", instance.handleClicked) if err != nil { - utils.LogError("PANIC!!! - CreateTemperaturePresetButton()", "instance.Button.Connect()", err) + logger.LogError("PANIC!!! - CreateTemperaturePresetButton()", "instance.Button.Connect()", err) panic(err) } @@ -45,13 +46,13 @@ func CreateTemperaturePresetButton( } func (this *TemperaturePresetButton) handleClicked() { - utils.Logger.Infof("TemperaturePresetButton.handleClicked() - setting temperature to preset %s.", this.temperaturePreset.Name) - utils.Logger.Infof("TemperaturePresetButton.handleClicked() - setting hotend temperature to %.0f.", this.temperaturePreset.Extruder) - utils.Logger.Infof("TemperaturePresetButton.handleClicked() - setting bed temperature to %.0f.", this.temperaturePreset.Bed) + logger.Infof("TemperaturePresetButton.handleClicked() - setting temperature to preset %s.", this.temperaturePreset.Name) + logger.Infof("TemperaturePresetButton.handleClicked() - setting hotend temperature to %.0f.", this.temperaturePreset.Extruder) + logger.Infof("TemperaturePresetButton.handleClicked() - setting bed temperature to %.0f.", this.temperaturePreset.Bed) currentTool := this.selectHotendStepButton.Value() if currentTool == "" { - utils.Logger.Error("TemperaturePresetButton.handleClicked() - currentTool is invalid (blank), defaulting to tool0") + logger.Error("TemperaturePresetButton.handleClicked() - currentTool is invalid (blank), defaulting to tool0") currentTool = "tool0" } @@ -77,7 +78,7 @@ func (this *TemperaturePresetButton) handleClicked() { bedTargetRequest := &octoprintApis.BedTargetRequest{Target: this.temperaturePreset.Bed} err := bedTargetRequest.Do(this.client) if err != nil { - utils.LogError("TemperaturePresetButton.handleClicked()", "Do(BedTargetRequest)", err) + logger.LogError("TemperaturePresetButton.handleClicked()", "Do(BedTargetRequest)", err) return } @@ -100,7 +101,7 @@ func (this *TemperaturePresetButton) handleClicked() { err = toolTargetRequest.Do(this.client) if err != nil { - utils.LogError("TemperaturePresetButton.handleClicked()", "Do(ToolTargetRequest)", err) + logger.LogError("TemperaturePresetButton.handleClicked()", "Do(ToolTargetRequest)", err) } if this.callback != nil { diff --git a/uiWidgets/TemperatureStatusBox.go b/uiWidgets/TemperatureStatusBox.go index fd2b8623..53556f9f 100755 --- a/uiWidgets/TemperatureStatusBox.go +++ b/uiWidgets/TemperatureStatusBox.go @@ -5,6 +5,7 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -24,13 +25,13 @@ func CreateTemperatureStatusBox( includeBed bool, ) *TemperatureStatusBox { if !includeHotends && !includeBed { - utils.Logger.Error("TemperatureStatusBox.CreateTemperatureStatusBox() - both includeToolheads and includeBed are false, but at least one needs to be true") + logger.Error("TemperatureStatusBox.CreateTemperatureStatusBox() - both includeToolheads and includeBed are false, but at least one needs to be true") return nil } currentTemperatureData, err := utils.GetCurrentTemperatureData(client) if err != nil { - utils.LogError("TemperatureStatusBox.CreateTemperatureStatusBox()", "GetCurrentTemperatureData(client)", err) + logger.LogError("TemperatureStatusBox.CreateTemperatureStatusBox()", "GetCurrentTemperatureData(client)", err) return nil } diff --git a/uiWidgets/ToolButton.go b/uiWidgets/ToolButton.go index 6b5f58ff..42fa821c 100755 --- a/uiWidgets/ToolButton.go +++ b/uiWidgets/ToolButton.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" "github.com/Z-Bolt/OctoScreen/utils" @@ -61,7 +62,7 @@ func CreateToolButton( _, err := instance.Connect("clicked", instance.clicked) if err != nil { - utils.LogError("ToolButton.CreateToolButton()", "t.Connect('clicked', t.clicked)", err) + logger.LogError("ToolButton.CreateToolButton()", "t.Connect('clicked', t.clicked)", err) } return instance @@ -89,7 +90,7 @@ func (this *ToolButton) GetProfileTemperature() float64 { settingsResponse, err := (&octoprintApis.SettingsRequest{}).Do(this.printer) if err != nil { - utils.LogError("ToolButton.GetProfileTemperature()", "Do(SettingsRequest)", err) + logger.LogError("ToolButton.GetProfileTemperature()", "Do(SettingsRequest)", err) return 0 } @@ -130,13 +131,13 @@ func (this *ToolButton) clicked() { cmd := &octoprintApis.BedTargetRequest{Target: target} err = cmd.Do(this.printer) if err != nil { - utils.LogError("ToolButton.clicked()", "Do(BedTargetRequest)", err) + logger.LogError("ToolButton.clicked()", "Do(BedTargetRequest)", err) } } else { cmd := &octoprintApis.ToolTargetRequest{Targets: map[string]float64{this.tool: target}} err = cmd.Do(this.printer) if err != nil { - utils.LogError("ToolButton.clicked()", "Do(ToolTargetRequest)", err) + logger.LogError("ToolButton.clicked()", "Do(ToolTargetRequest)", err) } } } diff --git a/utils/BackgroundTask.go b/utils/BackgroundTask.go index 51f66838..989dda8f 100755 --- a/utils/BackgroundTask.go +++ b/utils/BackgroundTask.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/gotk3/gotk3/glib" + "github.com/Z-Bolt/OctoScreen/logger" ) @@ -35,7 +36,7 @@ func (this *BackgroundTask) Start() { this.Lock() defer this.Unlock() - Logger.Info("New background task started") + logger.Info("New background task started") go this.loop() this.isRunning = true @@ -63,7 +64,7 @@ func (this *BackgroundTask) loop() { this.execute() case <-this.close: - Logger.Info("Background task closed") + logger.Info("Background task closed") return } } @@ -72,6 +73,6 @@ func (this *BackgroundTask) loop() { func (this *BackgroundTask) execute() { _, err := glib.IdleAdd(this.task) if err != nil { - LogFatalError("common.execute()", "IdleAdd()", err) + logger.LogFatalError("common.execute()", "IdleAdd()", err) } } diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go index e90f06aa..47aca455 100755 --- a/utils/LocationHistory.go +++ b/utils/LocationHistory.go @@ -4,6 +4,7 @@ import ( // "fmt" // "sort" + "github.com/Z-Bolt/OctoScreen/logger" // "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" // "github.com/Z-Bolt/OctoScreen/uiWidgets" @@ -20,7 +21,7 @@ func (this *LocationHistory) Length() int { func (this *LocationHistory) CurrentLocation() dataModels.Location { length := this.Length() if length < 1 { - log.Error("CurrentLocation() - length < 1") + logger.Error("CurrentLocation() - length < 1") panic("PANIC!!! - LocationHistory.current() - locations is empty") } diff --git a/utils/UpdateTemperaturesBackgroundTask.go b/utils/UpdateTemperaturesBackgroundTask.go index 43890645..35ea9798 100755 --- a/utils/UpdateTemperaturesBackgroundTask.go +++ b/utils/UpdateTemperaturesBackgroundTask.go @@ -4,6 +4,7 @@ import ( "time" "github.com/Z-Bolt/OctoScreen/interfaces" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -20,7 +21,7 @@ func CreateUpdateTemperaturesBackgroundTask( client *octoprintApis.Client, ) { if UpdateTemperaturesBackgroundTask != nil { - Logger.Error("UpdateTemperaturesBackgroundTask.CreateUpdateTemperaturesBackgroundTask() - updateTemperaturesBackgroundTask has already been set") + logger.Error("UpdateTemperaturesBackgroundTask.CreateUpdateTemperaturesBackgroundTask() - updateTemperaturesBackgroundTask has already been set") return } @@ -35,6 +36,7 @@ func RegisterTemperatureStatusBox(temperatureDataDisplay interfaces.ITemperature } func updateTemperaturesCallback() { + logger.TraceEnter("UpdateTemperaturesBackgroundTask.updateTemperaturesCallback()") // TODO: add guard if printer isn't connected // can't do right now due to circular dependency: @@ -45,11 +47,12 @@ func updateTemperaturesCallback() { currentTemperatureData, err := GetCurrentTemperatureData(registeredClient) if err != nil { - LogError("UpdateTemperaturesBackgroundTask.updateTemperaturesCallback()", "GetCurrentTemperatureData(client)", err) - return + logger.LogError("UpdateTemperaturesBackgroundTask.updateTemperaturesCallback()", "GetCurrentTemperatureData(client)", err) + } else { + for _, temperatureDataDisplay := range temperatureDataDisplays { + temperatureDataDisplay.UpdateTemperatureData(currentTemperatureData) + } } - for _, temperatureDataDisplay := range temperatureDataDisplays { - temperatureDataDisplay.UpdateTemperatureData(currentTemperatureData) - } + logger.TraceLeave("UpdateTemperaturesBackgroundTask.updateTemperaturesCallback()") } diff --git a/utils/environment.go b/utils/environment.go index 2dc07f0b..9fb6a591 100755 --- a/utils/environment.go +++ b/utils/environment.go @@ -4,6 +4,9 @@ import ( "fmt" "os" //"strings" + + + "github.com/Z-Bolt/OctoScreen/logger" ) @@ -80,12 +83,10 @@ func NameOfMissingRequiredEnvironmentVariable(apiKey string) string { } func DumpEnvironmentVariables() { - Logger.Info("") - Logger.Info("") - Logger.Info("Environment variables...") + logger.Info("Environment variables...") // Required environment variables - Logger.Infof("Required environment variables:") + logger.Info("Required environment variables:") dumpEnvironmentVariable(EnvBaseURL) // TODO: revisit this! @@ -103,17 +104,14 @@ func DumpEnvironmentVariables() { dumpEnvironmentVariable(EnvStylePath) // Optional environment variables - Logger.Info("") - Logger.Infof("Optional environment variables:") + logger.Info("") + logger.Info("Optional environment variables:") dumpEnvironmentVariable(EnvConfigFile) dumpEnvironmentVariable(EnvLogFilePath) dumpEnvironmentVariable(EnvLogLevel) dumpEnvironmentVariable(EnvResolution) // EnvResolution is optional. If not set, the window size will // default to the values defined in globalVars.go. - - Logger.Info("") - Logger.Info("") } func dumpEnvironmentVariable(key string) { @@ -122,7 +120,7 @@ func dumpEnvironmentVariable(key string) { value = MISSING_ENV_TOKEN } - Logger.Infof("key: %q, value: %q", key, value) + logger.Infof("key: %q, value: %q", key, value) } func dumpObfuscatedEnvironmentVariable(key string) { @@ -133,7 +131,7 @@ func dumpObfuscatedEnvironmentVariable(key string) { value = GetObfuscatedValue(value) } - Logger.Infof("key: %q, value: %q", key, value) + logger.Infof("key: %q, value: %q", key, value) } func GetObfuscatedValue(value string) string { diff --git a/utils/filament.go b/utils/filament.go index 8f802a8d..a2145fc4 100755 --- a/utils/filament.go +++ b/utils/filament.go @@ -4,6 +4,7 @@ import ( // "errors" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -25,15 +26,15 @@ func Extrude( } if CheckIfHotendTemperatureIsTooLow(client, extruderId, action, parentWindow) { - Logger.Error("filament.Extrude() - temperature is too low") + logger.Error("filament.Extrude() - temperature is too low") // No need to display an error - CheckIfHotendTemperatureIsTooLow() displays an error to the user // if the temperature is too low. return } - Logger.Infof("filament.Extrude() - setting flow rate percentage of %d", flowRatePercentage) + logger.Infof("filament.Extrude() - setting flow rate percentage of %d", flowRatePercentage) if err := SetFlowRate(client, flowRatePercentage); err != nil { - LogError("filament.Extrude()", "SetFlowRate()", err) + logger.LogError("filament.Extrude()", "SetFlowRate()", err) // TODO: display error? return } @@ -45,9 +46,9 @@ func Extrude( cmd.Amount = -length } - Logger.Infof("filament.Extrude() - sending extrude request with length of: %d", cmd.Amount) + logger.Infof("filament.Extrude() - sending extrude request with length of: %d", cmd.Amount) if err := cmd.Do(client); err != nil { - LogError("filament.Extrude()", "Do(ToolExtrudeRequest)", err) + logger.LogError("filament.Extrude()", "Do(ToolExtrudeRequest)", err) // TODO: display error? return } @@ -61,9 +62,9 @@ func SetFlowRate( cmd := &octoprintApis.ToolFlowRateRequest{} cmd.Factor = flowRatePercentage - Logger.Infof("filament.SetFlowRate() - changing flow rate to %d%%", cmd.Factor) + logger.Infof("filament.SetFlowRate() - changing flow rate to %d%%", cmd.Factor) if err := cmd.Do(client); err != nil { - LogError("filament.SetFlowRate()", "Go(ToolFlowRateRequest)", err) + logger.LogError("filament.SetFlowRate()", "Go(ToolFlowRateRequest)", err) return err } diff --git a/utils/gtk.go b/utils/gtk.go index e1dee49d..d96bc732 100755 --- a/utils/gtk.go +++ b/utils/gtk.go @@ -9,13 +9,14 @@ import ( "github.com/gotk3/gotk3/gdk" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" ) // MustWindow returns a new gtk.Window, if error panics. func MustWindow(windowType gtk.WindowType) *gtk.Window { win, err := gtk.WindowNew(windowType) if err != nil { - LogError("PANIC!!! - MustWindow()", "gtk.WindowNew()", err) + logger.LogError("PANIC!!! - MustWindow()", "gtk.WindowNew()", err) panic(err) } @@ -28,7 +29,7 @@ func MustWindow(windowType gtk.WindowType) *gtk.Window { func MustGrid() *gtk.Grid { grid, err := gtk.GridNew() if err != nil { - LogError("PANIC!!! - MustGrid()", "gtk.GridNew()", err) + logger.LogError("PANIC!!! - MustGrid()", "gtk.GridNew()", err) panic(err) } @@ -39,7 +40,7 @@ func MustGrid() *gtk.Grid { func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box { box, err := gtk.BoxNew(orientation, spacing) if err != nil { - LogError("PANIC!!! - MustBox()", "gtk.BoxNew()", err) + logger.LogError("PANIC!!! - MustBox()", "gtk.BoxNew()", err) panic(err) } @@ -50,7 +51,7 @@ func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box { func MustProgressBar() *gtk.ProgressBar { progressBar, err := gtk.ProgressBarNew() if err != nil { - LogError("PANIC!!! - MustProgressBar()", "gtk.ProgressBarNew()", err) + logger.LogError("PANIC!!! - MustProgressBar()", "gtk.ProgressBarNew()", err) panic(err) } @@ -61,7 +62,7 @@ func MustProgressBar() *gtk.ProgressBar { func MustLabel(format string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { - LogError("PANIC!!! - MustLabel()", "gtk.LabelNew()", err) + logger.LogError("PANIC!!! - MustLabel()", "gtk.LabelNew()", err) panic(err) } @@ -74,7 +75,7 @@ func MustLabel(format string, args ...interface{}) *gtk.Label { func MustLabelWithCssClass(format string, className string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { - LogError("PANIC!!! - MustLabelWithCssClass()", "gtk.LabelNew()", err) + logger.LogError("PANIC!!! - MustLabelWithCssClass()", "gtk.LabelNew()", err) panic(err) } @@ -90,7 +91,7 @@ func MustLabelWithCssClass(format string, className string, args ...interface{}) func MustLabelWithCssClasses(format string, classNames []string, args ...interface{}) *gtk.Label { label, err := gtk.LabelNew("") if err != nil { - LogError("PANIC!!! - MustLabelWithCssClasses()", "gtk.LabelNew()", err) + logger.LogError("PANIC!!! - MustLabelWithCssClasses()", "gtk.LabelNew()", err) panic(err) } @@ -137,7 +138,7 @@ func MustButtonImage(buttonlabel, imageFileName string, clicked func()) *gtk.But image := MustImageFromFile(imageFileName) button, err := gtk.ButtonNewWithLabel(buttonlabel) if err != nil { - LogError("PANIC!!! - MustButtonImage()", "gtk.ButtonNewWithLabel()", err) + logger.LogError("PANIC!!! - MustButtonImage()", "gtk.ButtonNewWithLabel()", err) panic(err) } @@ -158,7 +159,7 @@ func MustToggleButton(label string, imageFileName string, clicked func()) *gtk.T image := MustImageFromFile(imageFileName) button, err := gtk.ToggleButtonNewWithLabel(label) if err != nil { - LogError("PANIC!!! - MustToggleButton()", "gtk.ToggleButtonNewWithLabel()", err) + logger.LogError("PANIC!!! - MustToggleButton()", "gtk.ToggleButtonNewWithLabel()", err) panic(err) } @@ -178,7 +179,7 @@ func MustToggleButton(label string, imageFileName string, clicked func()) *gtk.T func MustButton(image *gtk.Image, clicked func()) *gtk.Button { button, err := gtk.ButtonNew() if err != nil { - LogError("PANIC!!! - MustButton()", "gtk.ButtonNew()", err) + logger.LogError("PANIC!!! - MustButton()", "gtk.ButtonNew()", err) panic(err) } @@ -195,7 +196,7 @@ func MustButton(image *gtk.Image, clicked func()) *gtk.Button { func MustButtonText(label string, clicked func()) *gtk.Button { button, err := gtk.ButtonNewWithLabel(label) if err != nil { - LogError("PANIC!!! - MustButtonText()", "gtk.ButtonNewWithLabel()", err) + logger.LogError("PANIC!!! - MustButtonText()", "gtk.ButtonNewWithLabel()", err) panic(err) } @@ -208,24 +209,24 @@ func MustButtonText(label string, clicked func()) *gtk.Button { func MustImageFromFileWithSize(imageFileName string, width, height int) *gtk.Image { if imageFileName == "" { - Logger.Error("MustImageFromFileWithSize() - imageFileName is empty") + logger.Error("MustImageFromFileWithSize() - imageFileName is empty") //debug.PrintStack() need to import "runtime/debug" } imageFilePath := imagePath(imageFileName) if !FileExists(imageFilePath) { - Logger.Error("MustImageFromFileWithSize() - imageFilePath is '" + imageFilePath + "', but doesn't exist") + logger.Error("MustImageFromFileWithSize() - imageFilePath is '" + imageFilePath + "', but doesn't exist") //debug.PrintStack() need to import "runtime/debug" } pixbuf, err := gdk.PixbufNewFromFileAtScale(imageFilePath, width, height, true) if err != nil { - LogError("gtk.MustImageFromFileWithSize()", "PixbufNewFromFileAtScale()", err) + logger.LogError("gtk.MustImageFromFileWithSize()", "PixbufNewFromFileAtScale()", err) } image, err := gtk.ImageNewFromPixbuf(pixbuf) if err != nil { - LogError("PANIC!!! - MustImageFromFileWithSize()", "gtk.ImageNewFromPixbuf()", err) + logger.LogError("PANIC!!! - MustImageFromFileWithSize()", "gtk.ImageNewFromPixbuf()", err) panic(err) } @@ -235,19 +236,19 @@ func MustImageFromFileWithSize(imageFileName string, width, height int) *gtk.Ima // MustImageFromFile returns a new gtk.Image based on the given file, if error panics. func MustImageFromFile(imageFileName string) *gtk.Image { if imageFileName == "" { - Logger.Error("MustImageFromFile() - imageFileName is empty") + logger.Error("MustImageFromFile() - imageFileName is empty") //debug.PrintStack() need to import "runtime/debug" } imageFilePath := imagePath(imageFileName) if !FileExists(imageFilePath) { - Logger.Error("MustImageFromFile() - imageFilePath is '" + imageFilePath + "', but doesn't exist") + logger.Error("MustImageFromFile() - imageFilePath is '" + imageFilePath + "', but doesn't exist") //debug.PrintStack() need to import "runtime/debug" } image, err := gtk.ImageNewFromFile(imageFilePath) if err != nil { - LogError("PANIC!!! - MustImageFromFile()", "gtk.ImageNewFromFile()", err) + logger.LogError("PANIC!!! - MustImageFromFile()", "gtk.ImageNewFromFile()", err) panic(err) } @@ -256,7 +257,7 @@ func MustImageFromFile(imageFileName string) *gtk.Image { func ImageFromUrl(imageUrl string) (*gtk.Image, error) { if imageUrl == "" { - Logger.Error("MustImageFromUrl() - imageUrl is empty") + logger.Error("MustImageFromUrl() - imageUrl is empty") return nil, errors.New("imageUrl is empty") } @@ -298,12 +299,12 @@ func ImageFromUrl(imageUrl string) (*gtk.Image, error) { func MustCSSProviderFromFile(css string) *gtk.CssProvider { cssProvider, err := gtk.CssProviderNew() if err != nil { - LogError("PANIC!!! - MustCSSProviderFromFile()", "gtk.CssProviderNew()", err) + logger.LogError("PANIC!!! - MustCSSProviderFromFile()", "gtk.CssProviderNew()", err) panic(err) } if err := cssProvider.LoadFromPath(filepath.Join(StylePath, css)); err != nil { - LogError("PANIC!!! - MustCSSProviderFromFile()", "cssProvider.LoadFromPath()", err) + logger.LogError("PANIC!!! - MustCSSProviderFromFile()", "cssProvider.LoadFromPath()", err) panic(err) } @@ -318,7 +319,7 @@ func imagePath(imageFileName string) string { func MustOverlay() *gtk.Overlay { overlay, err := gtk.OverlayNew() if err != nil { - LogError("PANIC!!! - MustOverlay()", "gtk.OverlayNew()", err) + logger.LogError("PANIC!!! - MustOverlay()", "gtk.OverlayNew()", err) panic(err) } diff --git a/utils/tools.go b/utils/tools.go index c67825b2..41669620 100755 --- a/utils/tools.go +++ b/utils/tools.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/gotk3/gotk3/gtk" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -20,13 +21,13 @@ func getCachedPrinterProfileData(client *octoprintApis.Client) { connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(client) if err != nil { - LogError("Tools.setCachedPrinterProfileData()", "version.Get()", err) + logger.LogError("Tools.setCachedPrinterProfileData()", "version.Get()", err) return } printerProfile, err := (&octoprintApis.PrinterProfilesRequest{Id: connectionResponse.Current.PrinterProfile}).Do(client) if err != nil { - LogError("Tools.setCachedPrinterProfileData()", "Do(PrinterProfilesRequest)", err) + logger.LogError("Tools.setCachedPrinterProfileData()", "Do(PrinterProfilesRequest)", err) return } @@ -79,18 +80,18 @@ func GetHasSharedNozzle(client *octoprintApis.Client) bool { func GetDisplayNameForTool(toolName string) string { // Since this is such a hack, lets add some bounds checking if toolName == "" { - Logger.Error("Tools..GetDisplayNameForTool() - toolName is empty") + logger.Error("Tools..GetDisplayNameForTool() - toolName is empty") return "" } lowerCaseName := strings.ToLower(toolName) if strings.LastIndex(lowerCaseName, "tool") != 0 { - Logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) + logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) return "" } if len(toolName) != 5 { - Logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) + logger.Errorf("Tools.GetDisplayNameForTool() - toolName is invalid, value passed in was: %q", toolName) return "" } @@ -103,84 +104,80 @@ func GetDisplayNameForTool(toolName string) string { func GetToolTarget(client *octoprintApis.Client, tool string) (float64, error) { - Logger.Debug("entering Tools.GetToolTarget()") - + logger.TraceEnter("Tools.GetToolTarget()") fullStateRespone, err := (&octoprintApis.FullStateRequest{ Exclude: []string{"sd", "state"}, }).Do(client) if err != nil { - LogError("tools.GetToolTarget()", "Do(StateRequest)", err) - - Logger.Debug("leaving Tools.GetToolTarget()") + logger.LogError("tools.GetToolTarget()", "Do(StateRequest)", err) + logger.TraceLeave("Tools.GetToolTarget()") return -1, err } currentTemperatureData, ok := fullStateRespone.Temperature.CurrentTemperatureData[tool] if !ok { - Logger.Debug("leaving Tools.GetToolTarget()") + logger.TraceLeave("Tools.GetToolTarget()") return -1, fmt.Errorf("unable to find tool %q", tool) } - Logger.Debug("leaving Tools.GetToolTarget()") + logger.TraceLeave("Tools.GetToolTarget()") return currentTemperatureData.Target, nil } func SetToolTarget(client *octoprintApis.Client, tool string, target float64) error { - Logger.Debug("entering Tools.SetToolTarget()") + logger.TraceEnter("Tools.SetToolTarget()") if tool == "bed" { cmd := &octoprintApis.BedTargetRequest{Target: target} - - Logger.Debug("leaving Tools.SetToolTarget()") + logger.TraceLeave("Tools.SetToolTarget()") return cmd.Do(client) } cmd := &octoprintApis.ToolTargetRequest{Targets: map[string]float64{tool: target}} - - Logger.Debug("leaving Tools.SetToolTarget()") + logger.TraceLeave("Tools.SetToolTarget()") return cmd.Do(client) } func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]dataModels.TemperatureData, error) { - Logger.Debug("entering Tools.GetCurrentTemperatureData()") + logger.TraceEnter("Tools.GetCurrentTemperatureData()") temperatureDataResponse, err := (&octoprintApis.TemperatureDataRequest{}).Do(client) if err != nil { - LogError("tools.GetCurrentTemperatureData()", "Do(TemperatureDataRequest)", err) - - Logger.Debug("leaving Tools.GetCurrentTemperatureData()") + logger.LogError("tools.GetCurrentTemperatureData()", "Do(TemperatureDataRequest)", err) + logger.TraceLeave("Tools.GetCurrentTemperatureData()") return nil, err } if temperatureDataResponse == nil { - Logger.Error("tools.GetCurrentTemperatureData() - temperatureDataResponse is nil") - - Logger.Debug("leaving Tools.GetCurrentTemperatureData()") + logger.Error("tools.GetCurrentTemperatureData() - temperatureDataResponse is nil") + logger.TraceLeave("Tools.GetCurrentTemperatureData()") return nil, err } // Can't test for temperatureDataResponse.TemperatureStateResponse == nil (type mismatch) if temperatureDataResponse.TemperatureStateResponse.CurrentTemperatureData == nil { - Logger.Error("tools.GetCurrentTemperatureData() - temperatureDataResponse.TemperatureStateResponse.CurrentTemperatureData is nil") - - Logger.Debug("leaving Tools.GetCurrentTemperatureData()") + logger.Error("tools.GetCurrentTemperatureData() - temperatureDataResponse.TemperatureStateResponse.CurrentTemperatureData is nil") + logger.TraceLeave("Tools.GetCurrentTemperatureData()") return nil, err } - Logger.Debug("leaving Tools.GetCurrentTemperatureData()") + logger.TraceLeave("Tools.GetCurrentTemperatureData()") return temperatureDataResponse.TemperatureStateResponse.CurrentTemperatureData, nil } func CheckIfHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, action string, parentWindow *gtk.Window) bool { + logger.TraceEnter("Tools.CheckIfHotendTemperatureIsTooLow()") + currentTemperatureData, err := GetCurrentTemperatureData(client) if err != nil { - LogError("tools.CurrentHotendTemperatureIsTooLow()", "GetCurrentTemperatureData()", err) + logger.LogError("tools.CurrentHotendTemperatureIsTooLow()", "GetCurrentTemperatureData()", err) + logger.TraceLeave("Tools.CheckIfHotendTemperatureIsTooLow()") return true } @@ -195,9 +192,11 @@ func CheckIfHotendTemperatureIsTooLow(client *octoprintApis.Client, extruderId, ) ErrorMessageDialogBox(parentWindow, errorMessage) + logger.TraceLeave("Tools.CheckIfHotendTemperatureIsTooLow()") return true } + logger.TraceLeave("Tools.CheckIfHotendTemperatureIsTooLow()") return false } @@ -237,8 +236,6 @@ func GetHotendFileName(hotendIndex, hotendCount int) string { - - func GetNozzleFileName(hotendIndex, hotendCount int) string { strImageFileName := "" if hotendIndex == 1 && hotendCount == 1 { @@ -265,10 +262,10 @@ func HotendTemperatureIsTooLow( parentWindow *gtk.Window, ) bool { targetTemperature := temperatureData.Target - Logger.Infof("tools.HotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) + logger.Infof("tools.HotendTemperatureIsTooLow() - targetTemperature is %.2f", targetTemperature) actualTemperature := temperatureData.Actual - Logger.Infof("tools.HotendTemperatureIsTooLow() - actualTemperature is %.2f", actualTemperature) + logger.Infof("tools.HotendTemperatureIsTooLow() - actualTemperature is %.2f", actualTemperature) if targetTemperature <= MIN_HOTEND_TEMPERATURE || actualTemperature <= MIN_HOTEND_TEMPERATURE { return true From 3d57adee7937e6b005cb88f3012adb84880d7931 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 09:44:40 -0800 Subject: [PATCH 56/94] updated code to use new logger library --- main.go | 190 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 96 insertions(+), 94 deletions(-) diff --git a/main.go b/main.go index 3b8102fa..4f63c4e8 100755 --- a/main.go +++ b/main.go @@ -12,9 +12,12 @@ import ( "github.com/gotk3/gotk3/gtk" "github.com/sirupsen/logrus" - "github.com/Z-Bolt/OctoScreen/octoprintApis" + + "github.com/Z-Bolt/OctoScreen/logger" + // "github.com/Z-Bolt/OctoScreen/octoprintApis" "github.com/Z-Bolt/OctoScreen/ui" "github.com/Z-Bolt/OctoScreen/utils" + "gopkg.in/yaml.v1" ) @@ -26,34 +29,12 @@ var ( Resolution string ) -func main() { - utils.Logger.Debug("OctoScreen - entering main.main()") - - gtk.Init(nil) - settings, _ := gtk.SettingsGetDefault() - settings.SetProperty("gtk-application-prefer-dark-theme", true) - - utils.DumpEnvironmentVariables() - - if utils.RequiredEnvironmentVariablesAreSet(APIKey) { - width, height := getSize() - // width and height come from EnvResolution/OCTOSCREEN_RESOLUTION - // and aren't required - if not set, ui.New() will use the default - // values (defined in globalVars.go). - _ = ui.New(BaseURL, APIKey, width, height) - } else { - fatalErrorWindow := ui.CreateFatalErrorWindow("Required environment variable is not set:", utils.NameOfMissingRequiredEnvironmentVariable(APIKey)) - fatalErrorWindow.ShowAll() - } - - gtk.Main() - - utils.Logger.Debug("OctoScreen - leaving main.main()") -} - func init() { - utils.Logger.Debug("OctoScreen - entering main.init()") + logger.Debug("-") + logger.Debug("-") + // logger.Debug("OctoScreen - entering main.init()") + logger.TraceEnter("OctoScreen - main.init()") ConfigFile = os.Getenv(utils.EnvConfigFile) if ConfigFile == "" { @@ -64,9 +45,9 @@ func init() { setApiKey(cfg) if !utils.RequiredEnvironmentVariablesAreSet(APIKey) { - utils.Logger.Error("OctoScreen - main.init() - RequiredEnvironmentVariablesAreSet() returned false") - - utils.Logger.Debug("OctoScreen - leaving main.init()") + logger.Error("OctoScreen - main.init() - RequiredEnvironmentVariablesAreSet() returned false") + // logger.Debug("OctoScreen - leaving main.init()") + logger.TraceLeave("OctoScreen - main.init()") return } @@ -76,40 +57,66 @@ func init() { Resolution = os.Getenv(utils.EnvResolution) setBaseUrl(cfg) - utils.Logger.Debug("OctoScreen - leaving main.init()") + // logger.Debug("OctoScreen - leaving main.init()") + logger.TraceLeave("OctoScreen - main.init()") + logger.Debug("-") + logger.Debug("-") } -func setLogLevel() { - logLevel := utils.LowerCaseLogLevel() - switch logLevel { - case "debug": - octoprintApis.EnableApiLogging = true +func main() { + logger.Debug("+") + logger.Debug("+") + logger.TraceEnter("OctoScreen - main.main()") - default: - octoprintApis.EnableApiLogging = false + gtk.Init(nil) + settings, _ := gtk.SettingsGetDefault() + settings.SetProperty("gtk-application-prefer-dark-theme", true) + + utils.DumpEnvironmentVariables() + + if utils.RequiredEnvironmentVariablesAreSet(APIKey) { + width, height := getSize() + // width and height come from EnvResolution/OCTOSCREEN_RESOLUTION + // and aren't required - if not set, ui.New() will use the default + // values (defined in globalVars.go). + _ = ui.New(BaseURL, APIKey, width, height) + } else { + fatalErrorWindow := ui.CreateFatalErrorWindow("Required environment variable is not set:", utils.NameOfMissingRequiredEnvironmentVariable(APIKey)) + fatalErrorWindow.ShowAll() } + gtk.Main() + + logger.TraceLeave("OctoScreen - main.main()") + logger.Debug("+") + logger.Debug("+") +} + + +func setLogLevel() { + logLevel := logger.LogLevel() + switch logLevel { case "debug": - utils.SetLogLevel(logrus.DebugLevel) + logger.SetLogLevel(logrus.DebugLevel) case "info": - utils.SetLogLevel(logrus.InfoLevel) + logger.SetLogLevel(logrus.InfoLevel) case "warn": - utils.SetLogLevel(logrus.WarnLevel) + logger.SetLogLevel(logrus.WarnLevel) case "": logLevel = "error" os.Setenv(utils.EnvLogLevel, "error") fallthrough case "error": - utils.SetLogLevel(logrus.ErrorLevel) + logger.SetLogLevel(logrus.ErrorLevel) default: // unknown log level, so exit - utils.Logger.Fatalf("main.setLogLevel() - unknown logLevel: %q", logLevel) + logger.Fatalf("main.setLogLevel() - unknown logLevel: %q", logLevel) } standardLog.Printf("main.SetLogLevel() - logLevel is now set to: %q", logLevel) @@ -126,32 +133,31 @@ func setBaseUrl(cfg *config) { } else { url := strings.ToLower(BaseURL) if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { - utils.Logger.Warn("WARNING! OCTOPRINT_HOST requires the transport protocol ('http://' or 'https://') but is missing. 'http://' is being added to BaseURL."); + logger.Warn("WARNING! OCTOPRINT_HOST requires the transport protocol ('http://' or 'https://') but is missing. 'http://' is being added to BaseURL."); BaseURL = fmt.Sprintf("http://%s", BaseURL) } } - utils.Logger.Infof("main.setBaseUrl() - using %q as server address", BaseURL) + logger.Infof("main.setBaseUrl() - using %q as server address", BaseURL) } func setApiKey(cfg *config) { - utils.Logger.Debug("OctoScreen - entering main.setApiKey()") + logger.TraceEnter("main.setApiKey()") APIKey = os.Getenv(utils.EnvAPIKey) if APIKey == "" { - utils.Logger.Debug("main.setApiKey() - APIKey is empty, now using cfg.API.Key") - + logger.Debug("main.setApiKey() - APIKey is empty, now using cfg.API.Key") APIKey = cfg.API.Key } if APIKey == "" { - utils.Logger.Debug("main.setApiKey() - APIKey is empty!") + logger.Debug("main.setApiKey() - APIKey is empty!") } else { obfuscatedApiKey := utils.GetObfuscatedValue(APIKey) - utils.Logger.Debugf("main.setApiKey() - APIKey is %q", obfuscatedApiKey) + logger.Debugf("main.setApiKey() - APIKey is %q", obfuscatedApiKey) } - utils.Logger.Debug("OctoScreen - leaving main.setApiKey()") + logger.TraceLeave("main.setApiKey()") } @@ -166,132 +172,128 @@ type config struct { // Key is the current API key needed for accessing the API. Key string } + // Server settings. Server struct { // Hosts define the host to which to bind the server, defaults to "0.0.0.0". Host string + // Port define the port to which to bind the server, defaults to 5000. Port int } } func readConfig(configFile string) *config { - utils.Logger.Debug("") - utils.Logger.Debug("") - utils.Logger.Debug("entering main.readConfig()") + logger.TraceEnter("main.readConfig()") cfg := &config{} if configFile == "" { - utils.Logger.Info("main.readConfig() - configFile is empty") - - utils.Logger.Debug("leaving main.readConfig(), returning the default config") + logger.Info("main.readConfig() - configFile is empty") + logger.TraceLeave("main.readConfig(), returning the default config") return cfg } else { - utils.Logger.Infof("Path to OctoPrint's config file: %q", configFile) + logger.Infof("Path to OctoPrint's config file: %q", configFile) } data, err := ioutil.ReadFile(configFile) if err != nil { - utils.Logger.Fatalf("main.readConfig() - ReadFile() returned an error: %q", err) + logger.Fatalf("main.readConfig() - ReadFile() returned an error: %q", err) } else { - utils.Logger.Info("main.readConfig() - ReadFile() succeeded") + logger.Info("main.readConfig() - ReadFile() succeeded") } if err := yaml.Unmarshal([]byte(data), cfg); err != nil { - utils.Logger.Fatalf("main.readConfig() - error decoding YAML config file %q: %s", configFile, err) + logger.Fatalf("main.readConfig() - error decoding YAML config file %q: %s", configFile, err) } else { - utils.Logger.Info("main.readConfig() - YAML config file was decoded") + logger.Info("main.readConfig() - YAML config file was decoded") } if cfg.Server.Host == "" { cfg.Server.Host = "localhost" } - utils.Logger.Infof("main.readConfig() - server host is: %q", cfg.Server.Host) + logger.Infof("main.readConfig() - server host is: %q", cfg.Server.Host) if cfg.Server.Port == 0 { cfg.Server.Port = 5000 } - utils.Logger.Infof("main.readConfig() - server port is: %d", cfg.Server.Port) - - - utils.Logger.Debug("leaving main.readConfig()") - utils.Logger.Debug("") - utils.Logger.Debug("") + logger.Infof("main.readConfig() - server port is: %d", cfg.Server.Port) + logger.TraceLeave("main.readConfig()") return cfg } func findConfigFile() string { - utils.Logger.Debug("entering main.findConfigFile()") + logger.TraceEnter("main.findConfigFile()") if file := doFindConfigFile(homeOctoPi); file != "" { - utils.Logger.Info("main.findConfigFile() - doFindConfigFile() found a file") - - utils.Logger.Debug("leaving main.findConfigFile(), returning the file") + logger.Info("main.findConfigFile() - doFindConfigFile() found a file") + logger.TraceLeave("main.findConfigFile(), returning the file") return file } usr, err := user.Current() if err != nil { - utils.LogError("main.findConfigFile()", "Current()", err) - - utils.Logger.Debug("leaving main.findConfigFile(), returning an empty string") + logger.LogError("main.findConfigFile()", "Current()", err) + logger.TraceLeave("main.findConfigFile(), returning an empty string") return "" } configFile := doFindConfigFile(usr.HomeDir) - utils.Logger.Debug("leaving main.findConfigFile(), returning configFile") + logger.TraceLeave("main.findConfigFile(), returning configFile") return configFile } func doFindConfigFile(home string) string { - utils.Logger.Debug("entering main.doFindConfigFile()") + logger.TraceEnter("main.doFindConfigFile()") path := filepath.Join(home, configLocation) - if _, err := os.Stat(path); err == nil { - utils.LogError("main.doFindConfigFile()", "Stat()", err) - - utils.Logger.Debug("leaving main.doFindConfigFile(), returning path") + logger.LogError("main.doFindConfigFile()", "Stat()", err) + logger.TraceLeave("main.doFindConfigFile(), returning path") return path } - utils.Logger.Debug("leaving main.doFindConfigFile(), returning an empty string") + logger.TraceLeave("main.doFindConfigFile(), returning an empty string") return "" } + + + + + + func getSize() (width, height int) { - utils.Logger.Debug("entering main.getSize()") + logger.TraceEnter("main.getSize()") if Resolution == "" { - utils.Logger.Info("main.getSize() - Resolution is empty, returning 0 for width and height, and will default to the default values defined in globalVars.go") - - utils.Logger.Debug("leaving main.getSize()") + logger.Info("main.getSize() - Resolution is empty, returning 0 for width and height, and will default to the default values defined in globalVars.go") + logger.TraceLeave("main.getSize()") return } parts := strings.SplitN(Resolution, "x", 2) if len(parts) != 2 { - utils.Logger.Error("main.getSize() - SplitN() - len(parts) != 2") - utils.Logger.Fatalf("main.getSize() - malformed %s variable: %q", utils.EnvResolution, Resolution) + logger.Error("main.getSize() - SplitN() - len(parts) != 2") + logger.Fatalf("main.getSize() - malformed %s variable: %q", utils.EnvResolution, Resolution) } var err error width, err = strconv.Atoi(parts[0]) if err != nil { - utils.LogError("main.getSize()", "Atoi(parts[0])", err) - utils.Logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) + logger.LogError("main.getSize()", "Atoi(parts[0])", err) + logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) } height, err = strconv.Atoi(parts[1]) if err != nil { - utils.LogError("main.getSize()", "Atoi(parts[1])", err) - utils.Logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) + logger.LogError("main.getSize()", "Atoi(parts[1])", err) + logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) } - utils.Logger.Debug("leaving main.getSize()") + logger.TraceLeave("main.getSize()") return } From a6c5db2f580ef189864986843c8137f2826eef49 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 10:23:50 -0800 Subject: [PATCH 57/94] updated the setting of OctoPrintPluginIsAvailable --- ui/ui.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/ui.go b/ui/ui.go index 4c4b4688..03d989ed 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -58,7 +58,7 @@ func New(endpoint, key string, width, height int) *UI { PanelHistory: stack.New(), Client: octoprintApis.NewClient(endpoint, key), NotificationsBox: uiWidgets.NewNotificationsBox(), - OctoPrintPluginIsAvailable: true, + OctoPrintPluginIsAvailable: false, Settings: nil, UIState: "__uninitialized__", @@ -350,17 +350,19 @@ func (this *UI) loadSettings() { // The call to GetSettings is also used to determine whether or not the // OctoScreen plug-in is available. If calling GetSettings returns // a 404, the plug-in isn't available. - this.OctoPrintPluginIsAvailable = false logger.Info("The OctoScreen plug-in is not available") } else { // If we get back any other kind of error, something bad happened, so log an error. logger.LogError("ui.loadSettings()", "Do(GetSettingsRequest)", err) } + this.OctoPrintPluginIsAvailable = false + logger.TraceLeave("ui.loadSettings()") return } else { logger.Info("The call to GetSettings succeeded and the OctoPrint plug-in is available") + this.OctoPrintPluginIsAvailable = true } if !this.validateMenuItems(settingsResponse.MenuStructure, "", true) { From b6734629a80d4bc8c57f19c13d48d3ca23ebe600 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 11:42:26 -0800 Subject: [PATCH 58/94] updated comment --- octoprintApis/dataModels/FileResponse.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/octoprintApis/dataModels/FileResponse.go b/octoprintApis/dataModels/FileResponse.go index 2b50756b..8b8d9c7e 100755 --- a/octoprintApis/dataModels/FileResponse.go +++ b/octoprintApis/dataModels/FileResponse.go @@ -75,7 +75,8 @@ type FileResponse struct { // Relative path to the preview thumbnail image (if it exists) - // The PrusaSlicer Thumbnails plug-in is required or this. + // The PrusaSlicer Thumbnails plug-in or the Cura Thumbnails plug-in + // is required for this. Thumbnail string `json:"thumbnail"` } From 15738ae4e74a025148a60ed5517b6af41bf7cc09 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Feb 2021 11:49:32 -0800 Subject: [PATCH 59/94] fixed typo in comment --- utils/ui_utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/ui_utils.go b/utils/ui_utils.go index 4c960587..05810bf4 100755 --- a/utils/ui_utils.go +++ b/utils/ui_utils.go @@ -75,7 +75,7 @@ func AttachToolheadButtonsToGrid(toolheadButtons []*gtk.Button, grid *gtk.Grid) // **************************************************************************** -// DislogBox Routines +// DialogBox Routines func MustConfirmDialogBox(parent *gtk.Window, msg string, cb func()) func() { return func() { win := gtk.MessageDialogNewWithMarkup( From 95fe39d5320153bfb21f655a47f4990e1c71cad0 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:19:49 -0800 Subject: [PATCH 60/94] changed a few logging statements from Info to Debug --- ui/FilesPanel.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index abbedfc5..24d9e21e 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -439,14 +439,14 @@ func (this *filesPanel) addThumbnail( listItemBox *gtk.Box, ) { if fileResponse.Thumbnail != "" { - logger.Infof("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) + logger.Debugf("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail) thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail) - logger.Infof("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) + logger.Debugf("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl) previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl) if imageFromUrlErr == nil { - logger.Infof("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it...") + logger.Debugf("FilesPanel.addItem() - no error from ImageNewFromPixbuf, now trying to add it...") bottomBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 0) From 80ddee857c4620d9874c070e2ec83daea6298ad8 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:21:59 -0800 Subject: [PATCH 61/94] fixed comment --- utils/gtk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/gtk.go b/utils/gtk.go index d96bc732..67d041e7 100755 --- a/utils/gtk.go +++ b/utils/gtk.go @@ -257,7 +257,7 @@ func MustImageFromFile(imageFileName string) *gtk.Image { func ImageFromUrl(imageUrl string) (*gtk.Image, error) { if imageUrl == "" { - logger.Error("MustImageFromUrl() - imageUrl is empty") + logger.Error("ImageFromUrl() - imageUrl is empty") return nil, errors.New("imageUrl is empty") } From 3bb0019369ad788e4124f0a1dda82d927a8dca96 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:25:52 -0800 Subject: [PATCH 62/94] cleaned up code in CreateSelectExtruderStepButton() and CreateSelectHotendStepButton() --- uiWidgets/SelectToolStepButton.go | 46 ++++++++++++++----------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/uiWidgets/SelectToolStepButton.go b/uiWidgets/SelectToolStepButton.go index be5a1754..d42a9cf0 100755 --- a/uiWidgets/SelectToolStepButton.go +++ b/uiWidgets/SelectToolStepButton.go @@ -23,21 +23,18 @@ func CreateSelectExtruderStepButton( var steps []Step for i := 0; i < extruderCount; i++ { - var step Step + label := "" if i == 0 && extruderCount == 1 { - step = Step { - "Extruder", - utils.GetExtruderFileName(1, extruderCount), - nil, - "tool0", - } + label = "Extruder" } else { - step = Step { - fmt.Sprintf("Extruder %d", i + 1), - utils.GetExtruderFileName(i + 1, extruderCount), - nil, - fmt.Sprintf("tool%d", i), - } + label = fmt.Sprintf("Extruder %d", i + 1) + } + + step := Step { + label, + utils.GetExtruderFileName(i + 1, extruderCount), + nil, + fmt.Sprintf("tool%d", i), } steps = append(steps, step) @@ -71,21 +68,18 @@ func CreateSelectHotendStepButton( var steps []Step for i := 0; i < hotendCount; i++ { - var step Step + label := "" if i == 0 && hotendCount == 1 { - step = Step { - "Hotend", - utils.GetHotendFileName(1, hotendCount), - nil, - "tool0", - } + label = "Hotend" } else { - step = Step { - fmt.Sprintf("Hotend %d", i + 1), - utils.GetHotendFileName(i + 1, hotendCount), - nil, - fmt.Sprintf("tool%d", i), - } + label = fmt.Sprintf("Hotend %d", i + 1) + } + + step := Step { + label, + utils.GetHotendFileName(i + 1, hotendCount), + nil, + fmt.Sprintf("tool%d", i), } steps = append(steps, step) From a6247e1355427a56d6b45be31ed3d931efbe8750 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Fri, 5 Mar 2021 22:32:45 +0000 Subject: [PATCH 63/94] Initial allow CustomControls with multiple command lines. (untested) --- ui/ControlPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ControlPanel.go b/ui/ControlPanel.go index 7f981b90..e86ac85e 100755 --- a/ui/ControlPanel.go +++ b/ui/ControlPanel.go @@ -81,7 +81,7 @@ func (this *controlPanel) getCustomControls() []*octoprint.ControlDefinition { for _, control := range response.Controls { for _, childControl := range control.Children { - if childControl.Command != "" || childControl.Script != "" { + if childControl.Command != "" || childControl.Script != "" || childControl.Commands != nil { controlDefinitions = append(controlDefinitions, childControl) } } From 662f24cef19b309ee578487a1fa250913db33a36 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Mar 2021 09:02:13 -0800 Subject: [PATCH 64/94] added mutex for _indentation to prevent race condition --- logger/logger.go | 66 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/logger/logger.go b/logger/logger.go index 1f34cd72..b3f1f224 100755 --- a/logger/logger.go +++ b/logger/logger.go @@ -8,14 +8,16 @@ import ( // "path" // "runtime" "strings" + "sync" // "time" "github.com/sirupsen/logrus" ) -var _indentLevel int -var _indentation string +var _mutex *sync.RWMutex = nil +var _indentLevel int = -1 +var _indentation string = "" const INDENTATION_TOKEN = " " const INDENTATION_TOKEN_LENGTH = 4 @@ -26,6 +28,8 @@ var _strLogLevel string func init() { + _mutex = &sync.RWMutex {} + _indentLevel = 0 _indentation = "" @@ -51,7 +55,7 @@ func init() { _logrusLogger.Out = io.MultiWriter(os.Stdout, file) logrus.SetOutput(_logrusLogger.Out) } else { - standardLog.Printf("logger.init() - OpenFile() FAILED! err is: %s", err.Error) + standardLog.Printf("logger.init() - OpenFile() FAILED! err is: %s", err.Error()) standardLog.Print("Failed to open the log file, defaulting to use the standard console output.") _logrusLogger.Out = os.Stdout } @@ -63,6 +67,21 @@ func init() { SetLogLevel(logrus.DebugLevel) } +func readIndentation() string { + _mutex.RLock() + var indentation = _indentation + _mutex.RUnlock() + + return indentation +} + +func writeIndentation(indentation string) { + _mutex.Lock() + _indentation = indentation + _mutex.Unlock() +} + + func SetLogLevel(newLevel logrus.Level) { _logLevel = newLevel _strLogLevel = strings.ToLower(_logLevel.String()) @@ -78,77 +97,82 @@ func LogLevel() string { func TraceEnter(functionName string) { - message := fmt.Sprintf("%sentering %s", _indentation, functionName) + message := fmt.Sprintf("%sentering %s", readIndentation(), functionName) _logrusEntry.Debug(message) _indentLevel++ - _indentation += INDENTATION_TOKEN + indentation := readIndentation() + INDENTATION_TOKEN + writeIndentation(indentation) } func TraceLeave(functionName string) { _indentLevel-- - _indentation = _indentation[:(_indentLevel * INDENTATION_TOKEN_LENGTH)] - message := fmt.Sprintf("%sleaving %s", _indentation, functionName) + + indentation := readIndentation() + indentation = indentation[:(_indentLevel * INDENTATION_TOKEN_LENGTH)] + writeIndentation(indentation) + + message := fmt.Sprintf("%sleaving %s", readIndentation(), functionName) _logrusEntry.Debug(message) } func LogError(currentFunctionName, functionCalledName string, err error) { if err != nil { - _logrusEntry.Errorf("%s%s - %s returned an error: %q", _indentation, currentFunctionName, functionCalledName, err) + _logrusEntry.Errorf("%s%s - %s returned an error: %q", readIndentation(), currentFunctionName, functionCalledName, err) } else { - _logrusEntry.Errorf("%s%s - %s returned an error", _indentation, currentFunctionName, functionCalledName) + _logrusEntry.Errorf("%s%s - %s returned an error", readIndentation(), currentFunctionName, functionCalledName) } } func LogFatalError(currentFunctionName, functionCalledName string, err error) { if err != nil { - _logrusEntry.Fatalf("%s%s - %s returned an error: %q", _indentation, currentFunctionName, functionCalledName, err) + _logrusEntry.Fatalf("%s%s - %s returned an error: %q", readIndentation(), currentFunctionName, functionCalledName, err) } else { - _logrusEntry.Fatalf("%s%s - %s returned an error", _indentation, currentFunctionName, functionCalledName) + _logrusEntry.Fatalf("%s%s - %s returned an error", readIndentation(), currentFunctionName, functionCalledName) } } func Debug(args ...interface{}) { - _logrusEntry.Debug(_indentation + fmt.Sprint(args...)) + _logrusEntry.Debug(readIndentation() + fmt.Sprint(args...)) } func Debugf(format string, args ...interface{}) { - _logrusEntry.Debugf(_indentation + format, args...) + _logrusEntry.Debugf(readIndentation() + format, args...) } func Info(args ...interface{}) { - _logrusEntry.Info(_indentation + fmt.Sprint(args...)) + _logrusEntry.Info(readIndentation() + fmt.Sprint(args...)) } func Infof(format string, args ...interface{}) { - _logrusEntry.Infof(_indentation + format, args...) + _logrusEntry.Infof(readIndentation() + format, args...) } func Warn(args ...interface{}) { - _logrusEntry.Warn(_indentation + fmt.Sprint(args...)) + _logrusEntry.Warn(readIndentation() + fmt.Sprint(args...)) } func Warnf(format string, args ...interface{}) { - _logrusEntry.Warnf(_indentation + format, args...) + _logrusEntry.Warnf(readIndentation() + format, args...) } func Error(args ...interface{}) { - _logrusEntry.Error(_indentation + fmt.Sprint(args...)) + _logrusEntry.Error(readIndentation() + fmt.Sprint(args...)) } func Errorf(format string, args ...interface{}) { - _logrusEntry.Errorf(_indentation + format, args...) + _logrusEntry.Errorf(readIndentation() + format, args...) } func Fatal(args ...interface{}) { - _logrusEntry.Fatal(_indentation + fmt.Sprint(args...)) + _logrusEntry.Fatal(readIndentation() + fmt.Sprint(args...)) } func Fatalf(format string, args ...interface{}) { - _logrusEntry.Fatalf(_indentation + format, args...) + _logrusEntry.Fatalf(readIndentation() + format, args...) } From 513dacbc13dfa82f541a29412e59d0986387a5d3 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Mar 2021 09:05:15 -0800 Subject: [PATCH 65/94] fixed bug in SystemCommandsRequest.Do() where Unmarshal() was being passed a string and not a *string --- octoprintApis/system.go | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/octoprintApis/system.go b/octoprintApis/system.go index 7e08c934..c879fdb5 100755 --- a/octoprintApis/system.go +++ b/octoprintApis/system.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + "github.com/Z-Bolt/OctoScreen/logger" "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels" ) @@ -22,33 +23,37 @@ type SystemCommandsRequest struct{} // Do sends an API request and returns the API response. func (cmd *SystemCommandsRequest) Do(c *Client) (*dataModels.SystemCommandsResponse, error) { - b, err := c.doJsonRequest("GET", SystemCommandsApiUri, nil, nil) + bytes, err := c.doJsonRequest("GET", SystemCommandsApiUri, nil, nil) if err != nil { return nil, err } - // TODO: there are 2 warnings here... the 2nd parameter into Unmarshal() - // is supposed to be a pointer. Change x.Confirm to &x.Confirm ? - // need to verify - - r := &dataModels.SystemCommandsResponse{} - if err := json.Unmarshal(b, r); err != nil { + response := &dataModels.SystemCommandsResponse{} + if err := json.Unmarshal(bytes, response); err != nil { return nil, err } - for i := range r.Core { - x := r.Core[i] - if err2 := json.Unmarshal(x.RawConfirm, x.Confirm); err2 != nil { - x.Confirm = "" + + for i := range response.Core { + commandDefinition := response.Core[i] + err = json.Unmarshal(commandDefinition.RawConfirm, &commandDefinition.Confirm) + if err != nil { + logger.LogError("SystemCommandsRequest.Do()", "json.Unmarshal(Core)", err) + commandDefinition.Confirm = "" + return nil, err } } - for i := range r.Custom { - x := r.Custom[i] - if err2 := json.Unmarshal(x.RawConfirm, x.Confirm); err2 != nil { - x.Confirm = "" + + for i := range response.Custom { + commandDefinition := response.Custom[i] + err = json.Unmarshal(commandDefinition.RawConfirm, &commandDefinition.Confirm) + if err != nil { + logger.LogError("SystemCommandsRequest.Do()", "json.Unmarshal(Custom)", err) + commandDefinition.Confirm = "" + return nil, err } } - return r, err + return response, err } // SystemExecuteCommandRequest retrieves all configured system commands. From fcf2c9b832c2fabfa5ef07dcb7f1e71a378f9f27 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Mar 2021 09:07:23 -0800 Subject: [PATCH 66/94] seperated out the refreshButton and backButton, added displayRootLocations() --- ui/FilesPanel.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 24d9e21e..b5439ac5 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -16,12 +16,15 @@ import ( "github.com/Z-Bolt/OctoScreen/utils" ) + var filesPanelInstance *filesPanel type filesPanel struct { CommonPanel listBox *gtk.Box + refreshButton *gtk.Button + backButton *gtk.Button locationHistory utils.LocationHistory } @@ -61,7 +64,7 @@ func (this *filesPanel) initialize() { this.doLoadFiles() } -func (this *filesPanel) createActionFooter() gtk.IWidget { +func (this *filesPanel) createActionFooter() *gtk.Box { actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5) actionBar.SetHAlign(gtk.ALIGN_END) actionBar.SetHExpand(true) @@ -69,18 +72,21 @@ func (this *filesPanel) createActionFooter() gtk.IWidget { actionBar.SetMarginBottom(5) actionBar.SetMarginEnd(5) - actionBar.Add(this.createRefreshButton()) - actionBar.Add(this.createBackButton()) + this.refreshButton = this.createRefreshButton() + actionBar.Add(this.refreshButton) + + this.backButton = this.createBackButton() + actionBar.Add(this.backButton) return actionBar } -func (this *filesPanel) createRefreshButton() gtk.IWidget { +func (this *filesPanel) createRefreshButton() *gtk.Button { image := utils.MustImageFromFileWithSize("refresh.svg", this.Scaled(40), this.Scaled(40)) return utils.MustButton(image, this.doLoadFiles) } -func (this *filesPanel) createBackButton() gtk.IWidget { +func (this *filesPanel) createBackButton() *gtk.Button { image := utils.MustImageFromFileWithSize("back.svg", this.Scaled(40), this.Scaled(40)) return utils.MustButton(image, func() { if this.locationHistory.Length() < 1 { @@ -98,21 +104,28 @@ func (this *filesPanel) createBackButton() gtk.IWidget { func (this *filesPanel) doLoadFiles() { utils.EmptyTheContainer(&this.listBox.Container) - sortedFiles := this.getSortedFiles() - if sortedFiles == nil { + if this.displayRootLocations() { this.addRootLocations() } else { + sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } this.listBox.ShowAll() } +func (this *filesPanel) displayRootLocations() bool { + if this.locationHistory.Length() < 1 { + return true + } else { + return false + } +} + func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { var files []*dataModels.FileResponse - length := this.locationHistory.Length() - if length < 1 { + if this.displayRootLocations() { return nil } From 454f25043464428ea6e9912a9b9435e34d6c1444 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Mar 2021 09:12:48 -0800 Subject: [PATCH 67/94] added logging to try and catch if the app unexpectedly quits --- main.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/main.go b/main.go index 4f63c4e8..67daf7c8 100755 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "os" "os/user" "path/filepath" + "runtime" "strconv" "strings" @@ -65,6 +66,55 @@ func init() { func main() { + defer func() { + standardLog.Println("main's defer() was called, now calling recover()") + rec := recover(); + if rec != nil { + standardLog.Println("main's defer() - recover:", rec) + } else { + standardLog.Println("main's defer() - recover was nil") + } + + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + + /* + programCounter, fileName, lineNumber, infoWasRecovered := runtime.Caller(2) + standardLog.Println("main's defer() - programCounter:", programCounter) + standardLog.Println("main's defer() - fileName:", fileName) + standardLog.Println("main's defer() - lineNumber:", lineNumber) + standardLog.Println("main's defer() - infoWasRecovered:", infoWasRecovered) + */ + + pc := make([]uintptr, 20) + numberOfPcEntries := runtime.Callers(0, pc) + if numberOfPcEntries > 10 { + numberOfPcEntries = 10 + } + + for i := 1; i < numberOfPcEntries; i++ { + /* + standardLog.Printf("main's defer() - [%d]", i) + standardLog.Printf("main's defer() - [%d]", numberOfPcEntries) + + programCounter, fileName, lineNumber, infoWasRecovered := runtime.Caller(i) + standardLog.Printf("main's defer() - programCounter[%d]: %v", i, programCounter) + standardLog.Printf("main's defer() - fileName[%d]: %v", i, fileName) + standardLog.Printf("main's defer() - lineNumber[%d]: %v", i, lineNumber) + standardLog.Printf("main's defer() - infoWasRecovered[%d]: %v", i, infoWasRecovered) + standardLog.Println("") + */ + + _, fileName, lineNumber, infoWasRecovered := runtime.Caller(i) + if infoWasRecovered { + standardLog.Printf("main's defer() - [%d] %s, line %d", i, fileName, lineNumber) + } + } + + standardLog.Println("main's defer() was called, now exiting func()") + }() + + logger.Debug("+") logger.Debug("+") logger.TraceEnter("OctoScreen - main.main()") From edca87737b6e2496b15d73a1361d1e7df1a5e3c7 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 13 Mar 2021 12:09:24 -0800 Subject: [PATCH 68/94] added call to sdRefreshRequest.Do() to refresh the file list when the curent target is sdcard --- ui/FilesPanel.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index b5439ac5..f959d3b7 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -5,6 +5,7 @@ import ( "os" "sort" "strings" + "time" "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" @@ -132,6 +133,20 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { current := this.locationHistory.CurrentLocation() logger.Infof("Loading list of files from: %s", string(current)) + if current == dataModels.SDCard { + sdRefreshRequest := &octoprintApis.SdRefreshRequest {} + err := sdRefreshRequest.Do(this.UI.Client) + if err != nil { + logger.LogError("getSortedFiles()", "sdRefreshRequest.Do()", err) + return []*dataModels.FileResponse{} + } else { + // Pause here for a second, because the preceding call to filesRequest.Do() + // doesn't work, and it returns a truncated list of files. Pausing here + // for a second seems to resolve the issue. + time.Sleep(1 * time.Second) + } + } + filesRequest := &octoprintApis.FilesRequest { Location: current, Recursive: false, From de81a3677448096c608627f254e798a7f0d9aef6 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Mar 2021 10:46:54 -0700 Subject: [PATCH 69/94] added calls to sdNotify(), refactred into handleRootLocationClick() --- ui/FilesPanel.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index f959d3b7..8749cacf 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/coreos/go-systemd/daemon" "github.com/dustin/go-humanize" "github.com/gotk3/gotk3/gtk" "github.com/Z-Bolt/OctoScreen/interfaces" @@ -244,19 +245,24 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * topBox.Add(actionBox) rootLocationButton, _ := gtk.ButtonNew() - rootLocationButton.Connect("clicked", func() { - this.locationHistory = utils.LocationHistory { - Locations: []dataModels.Location{location}, - } - - this.doLoadFiles() - }) - + rootLocationButton.Connect("clicked", handleRootLocationClick) rootLocationButton.Add(topBox) return rootLocationButton } +func (this *filesPanel) handleRootLocationClick() { + this.sdNotify(daemon.SdNotifyWatchdog) + + this.locationHistory = utils.LocationHistory { + Locations: []dataModels.Location{location}, + } + + this.doLoadFiles() + + this.sdNotify(daemon.SdNotifyReady) +} + func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) { var index int = 0 From b9a00066a7f46c96ad9572fe23d45e9761b8df95 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Mar 2021 10:56:31 -0700 Subject: [PATCH 70/94] added missing 'this' --- ui/FilesPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 8749cacf..a4cda3c6 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -245,7 +245,7 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * topBox.Add(actionBox) rootLocationButton, _ := gtk.ButtonNew() - rootLocationButton.Connect("clicked", handleRootLocationClick) + rootLocationButton.Connect("clicked", this.handleRootLocationClick) rootLocationButton.Add(topBox) return rootLocationButton From b3f7a7d1251ef3c064b8b4ef474854a45b6edb82 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Mar 2021 11:12:09 -0700 Subject: [PATCH 71/94] reverted click handler b/c it needs 'location' --- ui/FilesPanel.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index a4cda3c6..ba930770 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -245,22 +245,21 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * topBox.Add(actionBox) rootLocationButton, _ := gtk.ButtonNew() - rootLocationButton.Connect("clicked", this.handleRootLocationClick) - rootLocationButton.Add(topBox) + rootLocationButton.Connect("clicked", func() { + this.sdNotify(daemon.SdNotifyWatchdog) - return rootLocationButton -} + this.locationHistory = utils.LocationHistory { + Locations: []dataModels.Location{location}, + } -func (this *filesPanel) handleRootLocationClick() { - this.sdNotify(daemon.SdNotifyWatchdog) + this.doLoadFiles() - this.locationHistory = utils.LocationHistory { - Locations: []dataModels.Location{location}, - } + this.sdNotify(daemon.SdNotifyReady) + }) - this.doLoadFiles() + rootLocationButton.Add(topBox) - this.sdNotify(daemon.SdNotifyReady) + return rootLocationButton } func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) { From 3903a524c80479e75fbe3be0cdfcc96147bfea67 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sun, 14 Mar 2021 11:22:54 -0700 Subject: [PATCH 72/94] added 'UI' which was removed --- ui/FilesPanel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index ba930770..8b85da85 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -246,7 +246,7 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * rootLocationButton, _ := gtk.ButtonNew() rootLocationButton.Connect("clicked", func() { - this.sdNotify(daemon.SdNotifyWatchdog) + this.UI.sdNotify(daemon.SdNotifyWatchdog) this.locationHistory = utils.LocationHistory { Locations: []dataModels.Location{location}, @@ -254,7 +254,7 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * this.doLoadFiles() - this.sdNotify(daemon.SdNotifyReady) + this.UI.sdNotify(daemon.SdNotifyReady) }) rootLocationButton.Add(topBox) From 9483bb56b46d908029047ddeb5c038a0b541e36f Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Sun, 14 Mar 2021 21:06:03 +0000 Subject: [PATCH 73/94] Chech SD status prior to loading or going back. --- ui/FilesPanel.go | 55 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 8b85da85..71d6b0e4 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -90,25 +90,23 @@ func (this *filesPanel) createRefreshButton() *gtk.Button { func (this *filesPanel) createBackButton() *gtk.Button { image := utils.MustImageFromFileWithSize("back.svg", this.Scaled(40), this.Scaled(40)) - return utils.MustButton(image, func() { - if this.locationHistory.Length() < 1 { - this.UI.GoToPreviousPanel() - } else if this.locationHistory.IsRoot() { - this.locationHistory.GoBack() - this.doLoadFiles() - } else { - this.locationHistory.GoBack() - this.doLoadFiles() - } - }) + return utils.MustButton(image, this.goBack) } func (this *filesPanel) doLoadFiles() { utils.EmptyTheContainer(&this.listBox.Container) - if this.displayRootLocations() { - this.addRootLocations() - } else { + if this.isRoot() { + if this.refreshSD() { + this.addRootLocations() + } else { + this.locationHistory = utils.LocationHistory { + Locations: []dataModels.Location{dataModels.Local}, + } + } + } + + if !this.isRoot() { sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } @@ -116,7 +114,32 @@ func (this *filesPanel) doLoadFiles() { this.listBox.ShowAll() } -func (this *filesPanel) displayRootLocations() bool { +func (this *filesPanel) refreshSD() bool { + sdResponse, err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) + if err == nil { + return true + } else { + return false + } +} + +func (this *filesPanel) goBack() { + if this.isRoot() { + this.UI.GoToPreviousPanel() + } else if this.locationHistory.IsRoot() { + this.locationHistory.GoBack() + if this.refreshSD() { + this.doLoadFiles() + } else { + this.UI.GoToPreviousPanel() + } + } else { + this.locationHistory.GoBack() + this.doLoadFiles() + } +} + +func (this *filesPanel) isRoot() bool { if this.locationHistory.Length() < 1 { return true } else { @@ -127,7 +150,7 @@ func (this *filesPanel) displayRootLocations() bool { func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { var files []*dataModels.FileResponse - if this.displayRootLocations() { + if this.isRoot() { return nil } From b85c127ba28e1b1fe11a3c4755ead343363ee574 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 01:11:20 +0000 Subject: [PATCH 74/94] Well shoot. --- ui/FilesPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 71d6b0e4..007eb188 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -115,7 +115,7 @@ func (this *filesPanel) doLoadFiles() { } func (this *filesPanel) refreshSD() bool { - sdResponse, err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) + err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) if err == nil { return true } else { From 7ee7da6bf87e654fa9cb418cd72b5ba01a94afd8 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 02:04:32 +0000 Subject: [PATCH 75/94] Debug because... Oddness... --- ui/FilesPanel.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 007eb188..d2e1fdd8 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -51,6 +51,7 @@ func FilesPanel( } func (this *filesPanel) initialize() { + logger.Info("Begin (*filesPanel).initialize()") this.listBox = utils.MustBox(gtk.ORIENTATION_VERTICAL, 0) this.listBox.SetVExpand(true) @@ -64,6 +65,7 @@ func (this *filesPanel) initialize() { this.Grid().Add(box) this.doLoadFiles() + logger.Info("End (*filesPanel).initialize()") } func (this *filesPanel) createActionFooter() *gtk.Box { @@ -94,12 +96,16 @@ func (this *filesPanel) createBackButton() *gtk.Button { } func (this *filesPanel) doLoadFiles() { + logger.Info("Begin (*filesPanel).doLoadFiles()") utils.EmptyTheContainer(&this.listBox.Container) if this.isRoot() { + logger.Info("Determined True (*filesPanel).isRoot()") if this.refreshSD() { + logger.Info("Determined True (*filesPanel).refreshSD()") this.addRootLocations() } else { + logger.Info("Determined False (*filesPanel).refreshSD()") this.locationHistory = utils.LocationHistory { Locations: []dataModels.Location{dataModels.Local}, } @@ -107,11 +113,13 @@ func (this *filesPanel) doLoadFiles() { } if !this.isRoot() { + logger.Info("Determined False (*filesPanel).isRoot()") sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } this.listBox.ShowAll() + logger.Info("End (*filesPanel).doLoadFiles()") } func (this *filesPanel) refreshSD() bool { From 4501b8d88521a186fca5c4f2e1eea746afd0a45b Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 11:51:25 +0000 Subject: [PATCH 76/94] Logging? --- ui/FilesPanel.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index d2e1fdd8..f479163b 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -96,16 +96,16 @@ func (this *filesPanel) createBackButton() *gtk.Button { } func (this *filesPanel) doLoadFiles() { - logger.Info("Begin (*filesPanel).doLoadFiles()") + logger.Infof("Begin (*filesPanel).doLoadFiles(%s)", "nb") utils.EmptyTheContainer(&this.listBox.Container) if this.isRoot() { - logger.Info("Determined True (*filesPanel).isRoot()") + logger.Infof("Determined True (*filesPanel).isRoot(%s)", "nb") if this.refreshSD() { - logger.Info("Determined True (*filesPanel).refreshSD()") + logger.Infof("Determined True (*filesPanel).refreshSD(%s)", "nb") this.addRootLocations() } else { - logger.Info("Determined False (*filesPanel).refreshSD()") + logger.Infof("Determined False (*filesPanel).refreshSD(%s)", "nb") this.locationHistory = utils.LocationHistory { Locations: []dataModels.Location{dataModels.Local}, } @@ -113,13 +113,13 @@ func (this *filesPanel) doLoadFiles() { } if !this.isRoot() { - logger.Info("Determined False (*filesPanel).isRoot()") + logger.Infof("Determined False (*filesPanel).isRoot()", "nb") sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } this.listBox.ShowAll() - logger.Info("End (*filesPanel).doLoadFiles()") + logger.Infof("End (*filesPanel).doLoadFiles()", "nb") } func (this *filesPanel) refreshSD() bool { From fc972a63af3d879b4699c786cd1d30dd4a2d7328 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 12:29:58 +0000 Subject: [PATCH 77/94] Just trying to figure out where I am... --- ui/FilesPanel.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index f479163b..cc1b8907 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -34,7 +34,9 @@ func FilesPanel( ui *UI, parentPanel interfaces.IPanel, ) *filesPanel { + logger.Info("Begin filesPanel()") if filesPanelInstance == nil { + logger.Info("Making New filesPanel") locationHistory := utils.LocationHistory { Locations: []dataModels.Location{}, } @@ -47,6 +49,7 @@ func FilesPanel( filesPanelInstance = instance } + logger.Info("End filesPanel()") return filesPanelInstance } From 9191d7f85bff278c41534814ffd960d4e35e4288 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 13:23:51 +0000 Subject: [PATCH 78/94] Check the SD state after refresh request. --- ui/FilesPanel.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index cc1b8907..3af6ca2b 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -128,7 +128,12 @@ func (this *filesPanel) doLoadFiles() { func (this *filesPanel) refreshSD() bool { err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) if err == nil { - return true + sdState, err := (&octoprintApis.SdStateRequest {}).Do(this.UI.Client) + if err == nil && sdState.IsReady == true { + return true + } else { + return false + } } else { return false } From 516b47cdb989beae4f78bd88e7da63ae3554e580 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 14:26:24 +0000 Subject: [PATCH 79/94] Removing unneeded logs. --- ui/FilesPanel.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 3af6ca2b..5911e5be 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -54,7 +54,6 @@ func FilesPanel( } func (this *filesPanel) initialize() { - logger.Info("Begin (*filesPanel).initialize()") this.listBox = utils.MustBox(gtk.ORIENTATION_VERTICAL, 0) this.listBox.SetVExpand(true) @@ -68,7 +67,6 @@ func (this *filesPanel) initialize() { this.Grid().Add(box) this.doLoadFiles() - logger.Info("End (*filesPanel).initialize()") } func (this *filesPanel) createActionFooter() *gtk.Box { @@ -99,30 +97,21 @@ func (this *filesPanel) createBackButton() *gtk.Button { } func (this *filesPanel) doLoadFiles() { - logger.Infof("Begin (*filesPanel).doLoadFiles(%s)", "nb") utils.EmptyTheContainer(&this.listBox.Container) - if this.isRoot() { - logger.Infof("Determined True (*filesPanel).isRoot(%s)", "nb") if this.refreshSD() { - logger.Infof("Determined True (*filesPanel).refreshSD(%s)", "nb") this.addRootLocations() } else { - logger.Infof("Determined False (*filesPanel).refreshSD(%s)", "nb") this.locationHistory = utils.LocationHistory { Locations: []dataModels.Location{dataModels.Local}, } } } - if !this.isRoot() { - logger.Infof("Determined False (*filesPanel).isRoot()", "nb") sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } - this.listBox.ShowAll() - logger.Infof("End (*filesPanel).doLoadFiles()", "nb") } func (this *filesPanel) refreshSD() bool { From f6adc731443df792b0bde07f26e333fda4423464 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 15 Mar 2021 14:29:01 +0000 Subject: [PATCH 80/94] Removing more unneeded logs. --- ui/FilesPanel.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 5911e5be..2ad973e7 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -34,9 +34,7 @@ func FilesPanel( ui *UI, parentPanel interfaces.IPanel, ) *filesPanel { - logger.Info("Begin filesPanel()") if filesPanelInstance == nil { - logger.Info("Making New filesPanel") locationHistory := utils.LocationHistory { Locations: []dataModels.Location{}, } @@ -49,7 +47,6 @@ func FilesPanel( filesPanelInstance = instance } - logger.Info("End filesPanel()") return filesPanelInstance } From 3cecb767529cc716734ef50808d45ca16d00bfb9 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Tue, 16 Mar 2021 03:11:52 +0000 Subject: [PATCH 81/94] Seems like too easy of a fix. Not sure what was going on here, but... We never used the configured Log Level... Why? --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 67daf7c8..6a7fc91e 100755 --- a/main.go +++ b/main.go @@ -145,7 +145,7 @@ func main() { func setLogLevel() { - logLevel := logger.LogLevel() + logLevel := strings.ToLower(os.Getenv(utils.EnvLogLevel)) switch logLevel { case "debug": From 1756f5690fdbdd9b8f8d72a8622c38ed28fda025 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Tue, 16 Mar 2021 03:59:22 +0000 Subject: [PATCH 82/94] Increase Watchdog timer per documentation recomendations. The documentation for SdNotify make it very clear that we should be notifying the watchdog at least time/2 (which is to say [WatchdogSec/2]. The primary loop that has done this was `UI.update` although I see that additional calls were added to try to resolve the random reboots. The fact of the matter is, the timer was 10 seconds, and update was only called every 10 seconds... So... A delay of even a second, anywhere in the app, and the watchdog would restart the service. I see where some additional notifys were added, but to be honest, a 10 second timeout seems too short anyway, and cutting it so close was a gamble. So I raised the timeout, and while I did keep the notify in Files (although I did move it to what was really the heavy call), with the additional time, I don't really think it is nessesary. This additional buffer, and adhering to the documented call cadence, should resolve the random reboots (I know 2.7.0 was supposed to resolve these, likely due to the addition of the additional notify calls, however I just had a development board doing nothing reset, so...). Also, there was a Notify Ready in Files. That is reserved for Service Init, so I pulled that out. --- debian/octoscreen.service | 2 +- ui/FilesPanel.go | 6 ++---- ui/ui.go | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/debian/octoscreen.service b/debian/octoscreen.service index 7cbb15a0..6391ef1c 100644 --- a/debian/octoscreen.service +++ b/debian/octoscreen.service @@ -11,7 +11,7 @@ ExecStart=/usr/bin/xinit /usr/bin/OctoScreen -- :0 -nolisten tcp -nocursor ExecStartPost=/bin/bash /etc/octoscreen/disablescreenblank.sh 0 StandardOutput=journal Restart=always -WatchdogSec=10s +WatchdogSec=20s [Install] WantedBy=graphical.target diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 8b85da85..2e5fd56d 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -130,6 +130,8 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { if this.displayRootLocations() { return nil } + + this.UI.sdNotify(daemon.SdNotifyWatchdog) current := this.locationHistory.CurrentLocation() logger.Infof("Loading list of files from: %s", string(current)) @@ -246,15 +248,11 @@ func (this *filesPanel) createRootLocationButton(location dataModels.Location) * rootLocationButton, _ := gtk.ButtonNew() rootLocationButton.Connect("clicked", func() { - this.UI.sdNotify(daemon.SdNotifyWatchdog) - this.locationHistory = utils.LocationHistory { Locations: []dataModels.Location{location}, } this.doLoadFiles() - - this.UI.sdNotify(daemon.SdNotifyReady) }) rootLocationButton.Add(topBox) diff --git a/ui/ui.go b/ui/ui.go index 03d989ed..0276fc6f 100755 --- a/ui/ui.go +++ b/ui/ui.go @@ -156,8 +156,6 @@ var errMercyPeriod = time.Second * 10 func (this *UI) verifyConnection() { logger.TraceEnter("ui.verifyConnection()") - this.sdNotify(daemon.SdNotifyWatchdog) - newUIState := "<>" splashMessage := "<>" @@ -426,10 +424,11 @@ func (this *UI) validateMenuItems(menuItems []dataModels.MenuItem, name string, func (this *UI) update() { logger.TraceEnter("ui.update()") + this.sdNotify(daemon.SdNotifyWatchdog) + if this.connectionAttempts > 8 { logger.Info("ui.update() - this.connectionAttempts > 8") this.splashPanel.putOnHold() - this.sdNotify(daemon.SdNotifyWatchdog) logger.TraceLeave("ui.update()") return From 88015ff857f1d6e99fdeb8db907df28292f82e11 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 22 Mar 2021 11:45:55 +0000 Subject: [PATCH 83/94] SD Is Ready --- ui/FilesPanel.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 2ad973e7..592b2265 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -96,7 +96,7 @@ func (this *filesPanel) createBackButton() *gtk.Button { func (this *filesPanel) doLoadFiles() { utils.EmptyTheContainer(&this.listBox.Container) if this.isRoot() { - if this.refreshSD() { + if this.sdReady() { this.addRootLocations() } else { this.locationHistory = utils.LocationHistory { @@ -111,7 +111,7 @@ func (this *filesPanel) doLoadFiles() { this.listBox.ShowAll() } -func (this *filesPanel) refreshSD() bool { +func (this *filesPanel) sdReady() bool { err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) if err == nil { sdState, err := (&octoprintApis.SdStateRequest {}).Do(this.UI.Client) @@ -130,7 +130,7 @@ func (this *filesPanel) goBack() { this.UI.GoToPreviousPanel() } else if this.locationHistory.IsRoot() { this.locationHistory.GoBack() - if this.refreshSD() { + if this.sdReady() { this.doLoadFiles() } else { this.UI.GoToPreviousPanel() From 7abd0178ede0cc7d413b4e1433d2c0c3b817a7ea Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 22 Mar 2021 12:13:30 +0000 Subject: [PATCH 84/94] Method names are hard. ;-) --- ui/FilesPanel.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 592b2265..ac97b0f5 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -95,23 +95,28 @@ func (this *filesPanel) createBackButton() *gtk.Button { func (this *filesPanel) doLoadFiles() { utils.EmptyTheContainer(&this.listBox.Container) - if this.isRoot() { - if this.sdReady() { - this.addRootLocations() - } else { - this.locationHistory = utils.LocationHistory { - Locations: []dataModels.Location{dataModels.Local}, - } + atRootLevel := this.displayRootLocations() + /** + * If we are at `root` (display the option for SD AND Local), but SD is not + * ready, push us up and into Local so the user doesn't have to work harder + * than they have to. + */ + if atRootLevel && !this.sdIsReady() { + atRootLevel = false + this.locationHistory = utils.LocationHistory { + Locations: []dataModels.Location{dataModels.Local}, } } - if !this.isRoot() { + if atRootLevel { + this.addRootLocations() + } else { sortedFiles := this.getSortedFiles() this.addSortedFiles(sortedFiles) } this.listBox.ShowAll() } -func (this *filesPanel) sdReady() bool { +func (this *filesPanel) sdIsReady() bool { err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client) if err == nil { sdState, err := (&octoprintApis.SdStateRequest {}).Do(this.UI.Client) @@ -126,11 +131,11 @@ func (this *filesPanel) sdReady() bool { } func (this *filesPanel) goBack() { - if this.isRoot() { + if this.displayRootLocations() { this.UI.GoToPreviousPanel() } else if this.locationHistory.IsRoot() { this.locationHistory.GoBack() - if this.sdReady() { + if this.sdIsReady() { this.doLoadFiles() } else { this.UI.GoToPreviousPanel() @@ -141,7 +146,7 @@ func (this *filesPanel) goBack() { } } -func (this *filesPanel) isRoot() bool { +func (this *filesPanel) displayRootLocations() bool { if this.locationHistory.Length() < 1 { return true } else { @@ -152,7 +157,7 @@ func (this *filesPanel) isRoot() bool { func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { var files []*dataModels.FileResponse - if this.isRoot() { + if this.displayRootLocations() { return nil } From 9aafdc6ad9d7615c27a92a29ae453bdfe5d190b6 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Mon, 22 Mar 2021 12:36:16 +0000 Subject: [PATCH 85/94] Watchdog everything. --- ui/FilesPanel.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index 2e5fd56d..80dffd20 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -104,6 +104,9 @@ func (this *filesPanel) createBackButton() *gtk.Button { } func (this *filesPanel) doLoadFiles() { + + this.UI.sdNotify(daemon.SdNotifyWatchdog) + utils.EmptyTheContainer(&this.listBox.Container) if this.displayRootLocations() { @@ -130,8 +133,6 @@ func (this *filesPanel) getSortedFiles() []*dataModels.FileResponse { if this.displayRootLocations() { return nil } - - this.UI.sdNotify(daemon.SdNotifyWatchdog) current := this.locationHistory.CurrentLocation() logger.Infof("Loading list of files from: %s", string(current)) From a60e1c03f72f976947558f9c431208e041e286d0 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 22 Mar 2021 19:35:25 -0700 Subject: [PATCH 86/94] removed extra '*' --- ui/FilesPanel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/FilesPanel.go b/ui/FilesPanel.go index d7fba4c9..3d749f01 100755 --- a/ui/FilesPanel.go +++ b/ui/FilesPanel.go @@ -99,7 +99,7 @@ func (this *filesPanel) doLoadFiles() { utils.EmptyTheContainer(&this.listBox.Container) atRootLevel := this.displayRootLocations() - /** + /* * If we are at `root` (display the option for SD AND Local), but SD is not * ready, push us up and into Local so the user doesn't have to work harder * than they have to. From ed7e049318a128710c15fdfb9cf6c27dab05e4a4 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Mon, 22 Mar 2021 19:57:09 -0700 Subject: [PATCH 87/94] added Panic() and Panicln() --- logger/logger.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/logger/logger.go b/logger/logger.go index b3f1f224..910f6f2a 100755 --- a/logger/logger.go +++ b/logger/logger.go @@ -176,3 +176,11 @@ func Fatal(args ...interface{}) { func Fatalf(format string, args ...interface{}) { _logrusEntry.Fatalf(readIndentation() + format, args...) } + +func Panic(args ...interface{}) { + _logrusEntry.Panic(readIndentation() + fmt.Sprint(args...)) +} + +func Panicf(format string, args ...interface{}) { + _logrusEntry.Panicf(readIndentation() + format, args...) +} From 0728b9d0e82dfdbdeba8ed9a7e4ef80452631bdb Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Tue, 23 Mar 2021 22:26:01 -0700 Subject: [PATCH 88/94] remved calls to fatal(), reworked code so a FatalErrorWindow is displayed in all error cases --- main.go | 113 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 46 deletions(-) diff --git a/main.go b/main.go index 6a7fc91e..18a0ec32 100755 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "io/ioutil" standardLog "log" @@ -28,14 +29,15 @@ var ( APIKey string ConfigFile string Resolution string + initSucceeded bool ) func init() { logger.Debug("-") logger.Debug("-") - // logger.Debug("OctoScreen - entering main.init()") logger.TraceEnter("OctoScreen - main.init()") + initSucceeded = false ConfigFile = os.Getenv(utils.EnvConfigFile) if ConfigFile == "" { @@ -43,22 +45,18 @@ func init() { } cfg := readConfig(ConfigFile) - setApiKey(cfg) - - if !utils.RequiredEnvironmentVariablesAreSet(APIKey) { - logger.Error("OctoScreen - main.init() - RequiredEnvironmentVariablesAreSet() returned false") - // logger.Debug("OctoScreen - leaving main.init()") - logger.TraceLeave("OctoScreen - main.init()") + if cfg == nil { + initSucceeded = false return } + setApiKey(cfg) setLogLevel() - utils.StylePath = os.Getenv(utils.EnvStylePath) Resolution = os.Getenv(utils.EnvResolution) setBaseUrl(cfg) - // logger.Debug("OctoScreen - leaving main.init()") + initSucceeded = true logger.TraceLeave("OctoScreen - main.init()") logger.Debug("-") logger.Debug("-") @@ -125,15 +123,39 @@ func main() { utils.DumpEnvironmentVariables() - if utils.RequiredEnvironmentVariablesAreSet(APIKey) { - width, height := getSize() - // width and height come from EnvResolution/OCTOSCREEN_RESOLUTION - // and aren't required - if not set, ui.New() will use the default - // values (defined in globalVars.go). - _ = ui.New(BaseURL, APIKey, width, height) - } else { - fatalErrorWindow := ui.CreateFatalErrorWindow("Required environment variable is not set:", utils.NameOfMissingRequiredEnvironmentVariable(APIKey)) + if initSucceeded != true { + // readConfig() logs any errors it encounters. Don't display + // the error here, because the error could be long, and we don't + // want to display a long message and have the screen resize. + fatalErrorWindow := ui.CreateFatalErrorWindow( + "Initialization failed:", + "readConfig() failed, see log for errors", + ) fatalErrorWindow.ShowAll() + } else { + if utils.RequiredEnvironmentVariablesAreSet(APIKey) { + width, height, err := getSize() + if err == nil { + // width and height come from EnvResolution/OCTOSCREEN_RESOLUTION + // and aren't required - if not set, ui.New() will use the default + // values (defined in globalVars.go). + _ = ui.New(BaseURL, APIKey, width, height) + } else { + // But if there is an error while parsing OCTOSCREEN_RESOLUTION, + // then display the error. + fatalErrorWindow := ui.CreateFatalErrorWindow( + "getSize() failed", + err.Error(), + ) + fatalErrorWindow.ShowAll() + } + } else { + fatalErrorWindow := ui.CreateFatalErrorWindow( + "Required environment variable is not set:", + utils.NameOfMissingRequiredEnvironmentVariable(APIKey), + ) + fatalErrorWindow.ShowAll() + } } gtk.Main() @@ -165,8 +187,9 @@ func setLogLevel() { logger.SetLogLevel(logrus.ErrorLevel) default: - // unknown log level, so exit - logger.Fatalf("main.setLogLevel() - unknown logLevel: %q", logLevel) + // unknown log level + logLevel = "error" + logger.Errorf("main.setLogLevel() - unknown logLevel: %q, defaulting to error", logLevel) } standardLog.Printf("main.SetLogLevel() - logLevel is now set to: %q", logLevel) @@ -236,26 +259,26 @@ type config struct { func readConfig(configFile string) *config { logger.TraceEnter("main.readConfig()") - cfg := &config{} if configFile == "" { logger.Info("main.readConfig() - configFile is empty") - logger.TraceLeave("main.readConfig(), returning the default config") - return cfg - } else { - logger.Infof("Path to OctoPrint's config file: %q", configFile) + logger.TraceLeave("main.readConfig()") + return nil } + logger.Infof("Path to OctoPrint's config file: %q", configFile) + data, err := ioutil.ReadFile(configFile) if err != nil { - logger.Fatalf("main.readConfig() - ReadFile() returned an error: %q", err) - } else { - logger.Info("main.readConfig() - ReadFile() succeeded") + logger.Errorf("main.readConfig() - ReadFile() returned an error: %q", err) + logger.TraceLeave("main.readConfig()") + return nil } + cfg := &config{} if err := yaml.Unmarshal([]byte(data), cfg); err != nil { - logger.Fatalf("main.readConfig() - error decoding YAML config file %q: %s", configFile, err) - } else { - logger.Info("main.readConfig() - YAML config file was decoded") + logger.Errorf("main.readConfig() - error decoding YAML config file %q: %s", configFile, err) + logger.TraceLeave("main.readConfig()") + return nil } if cfg.Server.Host == "" { @@ -311,12 +334,7 @@ func doFindConfigFile(home string) string { } - - - - - -func getSize() (width, height int) { +func getSize() (width int, height int, err error) { logger.TraceEnter("main.getSize()") if Resolution == "" { @@ -328,20 +346,23 @@ func getSize() (width, height int) { parts := strings.SplitN(Resolution, "x", 2) if len(parts) != 2 { logger.Error("main.getSize() - SplitN() - len(parts) != 2") - logger.Fatalf("main.getSize() - malformed %s variable: %q", utils.EnvResolution, Resolution) + err = errors.New(fmt.Sprintf("%s is malformed\nvalue: %q", utils.EnvResolution, Resolution)) } - var err error - width, err = strconv.Atoi(parts[0]) - if err != nil { - logger.LogError("main.getSize()", "Atoi(parts[0])", err) - logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) + if err == nil { + width, err = strconv.Atoi(parts[0]) + if err != nil { + logger.LogError("main.getSize()", "Atoi(parts[0])", err) + err = errors.New(fmt.Sprintf("%s is malformed\nAtoi(0) failed\nvalue: %q", utils.EnvResolution, Resolution)) + } } - height, err = strconv.Atoi(parts[1]) - if err != nil { - logger.LogError("main.getSize()", "Atoi(parts[1])", err) - logger.Fatalf("main.getSize() - malformed %s variable: %q, %s", utils.EnvResolution, Resolution, err) + if err == nil { + height, err = strconv.Atoi(parts[1]) + if err != nil { + logger.LogError("main.getSize()", "Atoi(parts[1])", err) + err = errors.New(fmt.Sprintf("%s is malformed\nAtoi(1) failed\nvalue: %q", utils.EnvResolution, Resolution)) + } } logger.TraceLeave("main.getSize()") From e1cc6a3579dada1c12399b747deee588a03d85d1 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Wed, 24 Mar 2021 15:35:52 +0000 Subject: [PATCH 89/94] Fixed Command/Control Button Confirm dialog calling. --- uiWidgets/CommandButton.go | 15 +++++++++++---- uiWidgets/ControlButton.go | 14 ++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index 0a1e4282..e1c8adb3 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -41,20 +41,27 @@ func CreateCommandButton( } func (this *CommandButton) handleClicked() { + var handleClick func() + if len(this.commandDefinition.Confirm) != 0 { - utils.MustConfirmDialogBox(this.parentWindow, this.commandDefinition.Confirm, this.sendCommand) - return + logger.Debugf("CommandButton.handleClicked().MustConfirmDialogBox: %s", this.commandDefinition.Name) + handleClick = utils.MustConfirmDialogBox(this.parentWindow, this.commandDefinition.Confirm, this.sendCommand) } else { - this.sendCommand() + logger.Debugf("CommandButton.handleClicked().sendCommand: %s", this.commandDefinition.Name) + handleClick = this.sendCommand } + + handleClick() } func (this *CommandButton) sendCommand() { + logger.Debugf("CommandButton.sendCommand(): %q", this.commandDefinition.Name) + commandRequest := &octoprintApis.SystemExecuteCommandRequest{ Source: dataModels.Custom, Action: this.commandDefinition.Action, } - + err := commandRequest.Do(this.client) if err != nil { logger.LogError("CommandButton.sendCommand()", "Do(SystemExecuteCommandRequest)", err) diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index a8cd86af..f303ab9d 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -41,15 +41,22 @@ func CreateControlButton( } func (this *ControlButton) handleClicked() { + var handleClick func() + if len(this.controlDefinition.Confirm) != 0 { - utils.MustConfirmDialogBox(this.parentWindow, this.controlDefinition.Confirm, this.sendCommand) - return + logger.Debugf("ControlButton.handleClicked().MustConfirmDialogBox: %s", this.controlDefinition.Name) + handleClick = utils.MustConfirmDialogBox(this.parentWindow, this.controlDefinition.Confirm, this.sendCommand) } else { - this.sendCommand() + logger.Debugf("ControlButton.handleClicked().sendCommand: %s", this.controlDefinition.Name) + handleClick = this.sendCommand } + + handleClick() } func (this *ControlButton) sendCommand() { + logger.Debugf("ControlButton.sendCommand(): %q", this.controlDefinition.Name) + commandRequest := &octoprintApis.CommandRequest{ Commands: this.controlDefinition.Commands, } @@ -58,7 +65,6 @@ func (this *ControlButton) sendCommand() { commandRequest.Commands = []string{this.controlDefinition.Command} } - logger.Infof("Executing command %q", this.controlDefinition.Name) err := commandRequest.Do(this.client) if err != nil { logger.LogError("ControlButton.sendCommand()", "Do(CommandRequest)", err) From 40ac4076bb6f57ff238a29731f22fb10d0815ab9 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Wed, 24 Mar 2021 16:14:22 +0000 Subject: [PATCH 90/94] Add SPACE and define keyboard buttons visually. --- styles/z-bolt/style.css | 5 +++-- ui/ConnectionPanel.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css index 3721399e..be4fa948 100755 --- a/styles/z-bolt/style.css +++ b/styles/z-bolt/style.css @@ -145,8 +145,9 @@ entry { button.keyboard { font-size: 30px; - margin: 0px; - /* margin-bottom: 10px; */ + margin: 2px; + background-color: #538fbe; + border: 5px outset #2d6898; } .dialog { diff --git a/ui/ConnectionPanel.go b/ui/ConnectionPanel.go index 34b9182a..5ec3d433 100755 --- a/ui/ConnectionPanel.go +++ b/ui/ConnectionPanel.go @@ -22,7 +22,7 @@ var keyBoardChars = []byte{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '-', '=', '.', ',', '|', ':', ';', '/', '~', '`', '[', ']', '{', '}', - '±', '§', '\\', + '±', '§', '\\', ' ', } type connectionPanel struct { From f0897cb90f73188d3b0717266b2a2798adb33a02 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Fri, 26 Mar 2021 15:26:57 +0000 Subject: [PATCH 91/94] Go.Mod stub Must be over 1.14 to trigger automatic vendoring for potential linter usage. Should not impact building for JESSIE (testing). --- go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..00f6b357 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/Z-Bolt/OctoScreen + +go 1.14 From 8bab1880a47835a625dbe864d8c1fd56b91c17c1 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Mar 2021 10:41:30 -0700 Subject: [PATCH 92/94] cleaned up CommandButton.handleClicked() and ControlButton.handleClicked() --- uiWidgets/CommandButton.go | 16 +++++++--------- uiWidgets/ControlButton.go | 16 +++++++--------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index e1c8adb3..a65bcb1e 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -41,21 +41,19 @@ func CreateCommandButton( } func (this *CommandButton) handleClicked() { - var handleClick func() - if len(this.commandDefinition.Confirm) != 0 { - logger.Debugf("CommandButton.handleClicked().MustConfirmDialogBox: %s", this.commandDefinition.Name) - handleClick = utils.MustConfirmDialogBox(this.parentWindow, this.commandDefinition.Confirm, this.sendCommand) + utils.MustConfirmDialogBox( + this.parentWindow, + this.commandDefinition.Confirm, + this.sendCommand, + )() } else { - logger.Debugf("CommandButton.handleClicked().sendCommand: %s", this.commandDefinition.Name) - handleClick = this.sendCommand + this.sendCommand() } - - handleClick() } func (this *CommandButton) sendCommand() { - logger.Debugf("CommandButton.sendCommand(): %q", this.commandDefinition.Name) + logger.Infof("CommandButton.sendCommand(), now sending command %q", this.controlDefinition.Name) commandRequest := &octoprintApis.SystemExecuteCommandRequest{ Source: dataModels.Custom, diff --git a/uiWidgets/ControlButton.go b/uiWidgets/ControlButton.go index f303ab9d..232abed5 100755 --- a/uiWidgets/ControlButton.go +++ b/uiWidgets/ControlButton.go @@ -41,21 +41,19 @@ func CreateControlButton( } func (this *ControlButton) handleClicked() { - var handleClick func() - if len(this.controlDefinition.Confirm) != 0 { - logger.Debugf("ControlButton.handleClicked().MustConfirmDialogBox: %s", this.controlDefinition.Name) - handleClick = utils.MustConfirmDialogBox(this.parentWindow, this.controlDefinition.Confirm, this.sendCommand) + utils.MustConfirmDialogBox( + this.parentWindow, + this.controlDefinition.Confirm, + this.sendCommand, + )() } else { - logger.Debugf("ControlButton.handleClicked().sendCommand: %s", this.controlDefinition.Name) - handleClick = this.sendCommand + this.sendCommand() } - - handleClick() } func (this *ControlButton) sendCommand() { - logger.Debugf("ControlButton.sendCommand(): %q", this.controlDefinition.Name) + logger.Infof("ControlButton.sendCommand(), now sending command %q", this.controlDefinition.Name) commandRequest := &octoprintApis.CommandRequest{ Commands: this.controlDefinition.Commands, From b6fdb9d695e8e474b55db86117c634e6e0d39682 Mon Sep 17 00:00:00 2001 From: JeffB42 <10328858+JeffB42@users.noreply.github.com> Date: Sat, 27 Mar 2021 11:02:04 -0700 Subject: [PATCH 93/94] cleaned up CommandButton.handleClicked() and ControlButton.handleClicked() --- uiWidgets/CommandButton.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go index a65bcb1e..030d4c88 100755 --- a/uiWidgets/CommandButton.go +++ b/uiWidgets/CommandButton.go @@ -53,13 +53,13 @@ func (this *CommandButton) handleClicked() { } func (this *CommandButton) sendCommand() { - logger.Infof("CommandButton.sendCommand(), now sending command %q", this.controlDefinition.Name) - + logger.Infof("CommandButton.sendCommand(), now sending command %q", this.commandDefinition.Name) + commandRequest := &octoprintApis.SystemExecuteCommandRequest{ Source: dataModels.Custom, Action: this.commandDefinition.Action, } - + err := commandRequest.Do(this.client) if err != nil { logger.LogError("CommandButton.sendCommand()", "Do(SystemExecuteCommandRequest)", err) From 5141a02e6b83a5d679067e9eb278bba1eca16bf3 Mon Sep 17 00:00:00 2001 From: Michael J Mulligan Date: Fri, 26 Mar 2021 18:40:33 +0000 Subject: [PATCH 94/94] A clean start --- .github/workflows/golangci-lint.yml | 48 +++ .golangci.yml | 449 ++++++++++++++++++++++++++++ 2 files changed, 497 insertions(+) create mode 100644 .github/workflows/golangci-lint.yml create mode 100644 .golangci.yml diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 00000000..fb45fb2b --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,48 @@ +name: GolangCI Lint +on: + push: + paths: + - '**.go' + tags: + - v* + branches: + - master + - development + pull_request: + paths: + - '**.go' +jobs: + golangci: + name: Lint + runs-on: ubuntu-latest + # This is just temporary, until we upgrade `gotk3` to the latest version + # At this time, with our current version of `gotk3` there are a few bugs with `golang1.16.x` + strategy: + matrix: + go-version: [1.15.x] + steps: + - name: Git Checkout + uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential git-buildpackage fakeroot libcairo2-dev libgtk-3-dev git devscripts gccgo gcc libc-dev + # When we ARE able to use 1.16, this would be how we install `golang1.16.x` AND modify the `go env` (`golangci-lint` doesn't support this natively) + #- name: GolangCI INIT + # uses: golangci/golangci-lint-action@master + - name: Configure Golang ENV + # This ensures that the correct build flags are set for the linters. + # To have this be the ACTUAL installed versions, use + # go env -w GOFLAGS=-tags=gtk_$(pkg-config --modversion gtk+-3.0 | tr -t . _ | cut -d _ -f 1-2),pango_$(pkg-config --modversion pango | tr -t . _ | cut -d _ -f 1-2),gdk_pixbuf_$(pkg-config --modversion gdk-pixbuf-2.0 | tr -t . _ | cut -d _ -f 1-2),glib_$(pkg-config --modversion glib-2.0 | tr -t . _ | cut -d _ -f 1-2) + # I set it to these statics, as these are the statics used in the MakeFile, and are acceptable in leu of setting them to the explicit versions. + # Additionally, the `gtk_3_22` tag must be explicitly set for `golang1.16.x` at this time, as the current `gotk3` package (current `master, not our packaged version) has an issue with `1.16.x`. This may change in the future, will have to run more tests. + run: | + go version + go env -w GOFLAGS=-tags=gtk_3_22,glib_2_58,pango_1_42,gdk_pixbuf_2_38 + go env + - name: GolangCI Lint + uses: golangci/golangci-lint-action@master + with: + version: v1.39.0 + skip-go-installation: true + only-new-issues: true + # FIXME Only for the time being, we should comment this out once we are comfortable with it. + args: --issues-exit-code 0 diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..aa3e1ce8 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,449 @@ +run: + + # timeout for analysis, e.g. 30s, 5m, default is 1m + # + # OctoScreen Note: + # Build on a Pi takes ~25m, so we give it some headroom + timeout: 60m + + # include test files or not, default is true + # + # OctoScreen Note: + # We don't generate test structures, this may speed up the linter. + tests: false + + issues-exit-code: 1 + + # which dirs to skip: issues from them won't be reported; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but default dirs are skipped independently + # from this option's value (see skip-dirs-use-default). + # + # OctoScreen Note: + # We have edited files in vendors, so don't skip it; even though that would + # be ideal in an ideal world. Maybe we add specific vendor directories that + # we have not edited, or will not edit. + #skip-dirs: + # - vendor + + # default is true. Enables skipping of directories: + # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + # + # OctoScreen Note: + # We have edited files in `./vendor/`, so... tsk tsk + skip-dirs-use-default: false + + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + modules-download-mode: vendor + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + # default is "colored-line-number" + format: colored-line-number + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + + # make issues output unique by line, default is true + uniq-by-line: false + + # add a prefix to the output file references; default is no prefix + path-prefix: "" + + # sorts results by: filepath, line and column + sort-results: true + + +# all available settings of specific linters +linters-settings: + dogsled: + # checks assignments with too many blank identifiers; default is 2 + max-blank-identifiers: 2 + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + errcheck: + # report about not checking of errors in type assertions: `a := b.(MyStruct)`; + # default is false: such cases aren't reported by default. + check-type-assertions: false + + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: false + exhaustive: + # check switch statements in generated files also + check-generated: false + # indicates that switch statements are to be considered exhaustive if a + # 'default' case is present, even if all enum members aren't listed in the + # switch + default-signifies-exhaustive: true +# exhaustivestruct: +# struct-patterns: +# - '*.Test' +# - '*.Test2' +# - '*.Embedded' +# - '*.External' + funlen: + lines: 60 + statements: 40 + gci: + # put imports beginning with prefix after 3rd-party packages; + # only support one prefix + # if not set, use goimports.local-prefixes # which we do +# local-prefixes: github.com/Z-Bolt/OctoScreen + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + nestif: + # minimal complexity of if statements to report, 5 by default + min-complexity: 5 + goconst: + # minimal length of string constant, 3 by default + min-len: 3 + # minimal occurrences count to trigger, 3 by default + min-occurrences: 3 + gocritic: + + # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. + # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". + enabled-tags: + - performance + - style + - diagnostic + disabled-tags: + - experimental + - opinionated + + # Settings passed to gocritic. + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be find in https://go-critic.github.io/overview. +# settings: +# captLocal: # must be valid enabled check name +# # whether to restrict checker to params only (default true) +# paramsOnly: true +# elseif: +# # whether to skip balanced if-else pairs (default true) +# skipBalanced: true +# hugeParam: +# # size in bytes that makes the warning trigger (default 80) +# sizeThreshold: 80 +# nestingReduce: +# # min number of statements inside a branch to trigger a warning (default 5) +# bodyWidth: 5 +# rangeExprCopy: +# # size in bytes that makes the warning trigger (default 512) +# sizeThreshold: 512 +# # whether to check test functions (default true) +# skipTestFuncs: true +# rangeValCopy: +# # size in bytes that makes the warning trigger (default 128) +# sizeThreshold: 32 +# # whether to check test functions (default true) +# skipTestFuncs: true +# ruleguard: +# # path to a gorules file for the ruleguard checker +# rules: '' +# truncateCmp: +# # whether to skip int/uint/uintptr types (default true) +# skipArchDependent: true +# underef: +# # whether to skip (*x).method() calls where x is a pointer receiver (default true) +# skipRecvDeref: true +# unnamedResult: +# # whether to check exported functions +# checkExported: true + cyclop: + # the maximal code complexity to report + max-complexity: 10 + # the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0) + package-average: 0.0 + # should ignore tests (default false) + skip-tests: false + godot: + # comments to be checked: `declarations`, `toplevel`, or `all` + scope: declarations + # list of regexps for excluding particular comment lines from check +# exclude: +# # example: exclude comments which contain numbers +# # - '[0-9]+' +# # check that each sentence starts with a capital letter +# capital: false + godox: + # report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging + keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting + - TODO + - BUG + - FIXME + - NOTE + - OPTIMIZE # marks code that should be optimized before merging + - HACK # marks hack-arounds that should be removed before merging + goimports: + # put imports beginning with prefix after 3rd-party packages; + # it's a comma-separated list of prefixes + local-prefixes: github.com/Z-Bolt/OctoScreen + golint: + # minimal confidence for issues, default is 0.8 + min-confidence: 0.8 + gomnd: + settings: + mnd: + # the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. + checks: argument,case,condition,operation,return,assign + # ignored-numbers: 1000 + # ignored-files: magic_.*.go + # ignored-functions: math.* + govet: + # report about shadowed variables + check-shadowing: true + + # settings per analyzer + settings: + printf: # analyzer name, run `go tool vet help` to see all analyzers + funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + + # enable or disable analyzers by name + # run `go tool vet help` to see all analyzers +# enable: +# - atomicalign + enable-all: true +# disable: +# - shadow +# disable-all: false + ifshort: + # Maximum length of variable declaration measured in number of lines, after which linter won't suggest using short syntax. + # Has higher priority than max-decl-chars. + max-decl-lines: 1 + # Maximum length of variable declaration measured in number of characters, after which linter won't suggest using short syntax. + max-decl-chars: 30 + gofumpt: + # Choose whether or not to use the extra rules that are disabled + # by default + extra-rules: true + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 80 + # tab width in spaces. Default to 1. + tab-width: 4 + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 30 +# prealloc: +# # XXX: we don't recommend using this linter before doing performance profiling. +# # For most programs usage of prealloc will be a premature optimization. +# +# # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. +# # True by default. +# simple: true +# range-loops: true # Report preallocation suggestions on range loops, true by default +# for-loops: false # Report preallocation suggestions on for loops, false by default + predeclared: + # comma-separated list of predeclared identifiers to not report on + ignore: "" + # include method names and field names (i.e., qualified names) in checks + q: false + nolintlint: + # Enable to ensure that nolint directives are all used. Default is true. +# allow-unused: false + # Disable to ensure that nolint directives don't have a leading space. Default is true. + allow-leading-space: false + # Exclude following linters from requiring an explanation. Default is []. + allow-no-explanation: [] + # Enable to require an explanation of nonzero length after each nolint directive. Default is false. + require-explanation: true + # Enable to require nolint directives to mention the specific linter being suppressed. Default is false. + require-specific: true + unparam: + # Inspect exported functions, default is false. Set to true if no external program/library imports your code. + # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find external interfaces. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + check-exported: false + unused: + # treat code as a program (not a library) and report unused exported identifiers; default is false. + # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find funcs usages. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + # + # OctoScreen Note: + # Breaks on GTK3 for some reason + # "failed to load package gtk: could not load export data: no export data for \"github.com/gotk3/gotk3/gtk\"" + check-exported: false + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + wsl: + # If true append is only allowed to be cuddled if appending value is + # matching variables, fields or types on line above. Default is true. + strict-append: true + # Allow calls and assignments to be cuddled as long as the lines have any + # matching variables, fields or types. Default is true. + allow-assign-and-call: true + # Allow assignments to be cuddled with anything. Default is false. + allow-assign-and-anything: false + # Allow multiline assignments to be cuddled. Default is true. + allow-multiline-assign: true + # Allow declarations (var) to be cuddled. + allow-cuddle-declarations: false + # Allow trailing comments in ending of blocks + allow-trailing-comment: false + # Force newlines in end of case at this limit (0 = never). + force-case-trailing-whitespace: 0 + # Force cuddling of err checks with err var assignment + force-err-cuddling: false + # Allow leading comments to be separated with empty lines + allow-separated-leading-comment: false + errorlint: + # Report non-wrapping error creation using fmt.Errorf + errorf: true + makezero: + # Allow only slices initialized with a length of zero. Default is false. + always: false +# forbidigo: +# # Forbid the following identifiers +# forbid: +# - fmt.Errorf # consider errors.Errorf in github.com/pkg/errors +# - fmt.Print.* # too much log noise +# - ginkgo\\.F.* # these are used just for local development +# # Exclude godoc examples from forbidigo checks. Default is true. +# exclude_godoc_examples: false + +linters: + + enable: + - dogsled + - dupl + - errcheck + - exhaustive + - funlen +# `gci` has issues with `golang1.15.x` and `golang1.16.x` has issues with our packaged version of `gotk3` +# We can uncomment this once `golang1.16.x` vs `gotk3` (including our packaged version) is resolved +# - gci + - gocognit + - nestif + - goconst + - gocritic + - cyclop + - godot + - godox + - goimports + - stylecheck + - gomnd + - govet + - ifshort + - gofumpt + - lll + - misspell + - nakedret + - predeclared + - nolintlint + - unparam + - gas + - unused + - whitespace + - wsl + - errorlint + - makezero + disable-all: true +# disable: +# # Going to try to disable the ones that seem to be throwing errors, for now. +# - unused +# - makezero +# presets: +# - bugs +# - unused + fast: false + +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + #exclude: + # - abcdef + + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. +# - path: ".*github.com/gotk3/.*" +# linters: +# - unused + + + # Exclude lll issues for long lines with go:generate + - linters: + - lll + source: "^//go:generate " + + # Independently from option `exclude` we use default exclude patterns, + # it can be disabled by this option. To list all + # excluded by default patterns execute `golangci-lint run --help`. + # Default value for this option is true. + #exclude-use-default: true + + # The default value is false. If set to true exclude and exclude-rules + # regular expressions become case sensitive. + exclude-case-sensitive: false + + # The list of ids of default excludes to include or disable. By default it's empty. +# include: +# - EXC0002 # disable excluding of issues about comments from golint + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + # + # OctoScreen Note: + # We set this to TRUE so you could, in theory, run this from the CLI. + # The GitHub Action will overwrite this and set it to FALSE. + new: true + +severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false + + # Default value is empty list. + # When a list of severity rules are provided, severity information will be added to lint + # issues. Severity rules have the same filtering capability as exclude rules except you + # are allowed to specify one matcher per severity rule. + # Only affects out formats that support setting severity information. + rules: + - linters: + - dupl + severity: warning