Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Z-Bolt/OctoScreen.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffB42 <10328858+JeffB42@users.noreply.github.com>2021-03-27 21:30:53 +0300
committerGitHub <noreply@github.com>2021-03-27 21:30:53 +0300
commit1f409741b50704b830a5c178eb6a80f21576f3de (patch)
tree1d0bfea729f4fc9855796a1eb317348663d5ed7e
parent7ef3c0277b084a9730210922b790372a2ec2c5d8 (diff)
parentb6fdb9d695e8e474b55db86117c634e6e0d39682 (diff)
Merge pull request #272 from Z-Bolt/2.7.0-devv2.7.0v2.6.1v2.6.0
merge 2.7.0-dev into master
-rwxr-xr-x[-rw-r--r--]Makefile2
-rw-r--r--debian/octoscreen.service2
-rwxr-xr-xdocs/ButtonImages.html45
-rwxr-xr-xinterfaces/ITemperatureDataDisplay.go5
-rwxr-xr-xlogger/contextHook.go38
-rwxr-xr-xlogger/logger.go186
-rwxr-xr-xmain.go295
-rwxr-xr-xoctoprintApis/BedOffsetRequest.go39
-rwxr-xr-xoctoprintApis/BedStateRequest.go43
-rwxr-xr-xoctoprintApis/BedTargetRequest.go39
-rwxr-xr-xoctoprintApis/CancelRequest.go26
-rwxr-xr-xoctoprintApis/CommandRequest.go31
-rwxr-xr-xoctoprintApis/ConnectRequest.go68
-rwxr-xr-xoctoprintApis/ConnectionRequest.go38
-rwxr-xr-xoctoprintApis/CustomCommandsRequest.go30
-rwxr-xr-xoctoprintApis/DeleteFileRequest.go29
-rwxr-xr-xoctoprintApis/DisconnectRequest.go44
-rwxr-xr-xoctoprintApis/FakesAckRequest.go49
-rwxr-xr-xoctoprintApis/FileRequest.go53
-rwxr-xr-xoctoprintApis/FilesRequest.go47
-rwxr-xr-xoctoprintApis/FullStateRequest.go83
-rwxr-xr-xoctoprintApis/JobRequest.go29
-rwxr-xr-xoctoprintApis/LICENSE21
-rwxr-xr-xoctoprintApis/NotificationRequest.go33
-rwxr-xr-xoctoprintApis/OctoScreenSettingsRequest.go31
-rwxr-xr-xoctoprintApis/PauseRequest.go40
-rwxr-xr-xoctoprintApis/PluginManagerInfoRequest.go42
-rwxr-xr-xoctoprintApis/PrintHeadHomeRequest.go39
-rwxr-xr-xoctoprintApis/PrintHeadJogRequest.go59
-rwxr-xr-xoctoprintApis/PrinterProfilesRequest.go30
-rwxr-xr-xoctoprintApis/README.md146
-rwxr-xr-xoctoprintApis/RestartRequest.go28
-rwxr-xr-xoctoprintApis/RunZOffsetCalibrationRequest.go27
-rwxr-xr-xoctoprintApis/SdInitRequest.go22
-rwxr-xr-xoctoprintApis/SdRefreshRequest.go20
-rwxr-xr-xoctoprintApis/SdReleaseRequest.go22
-rwxr-xr-xoctoprintApis/SdStateRequest.go31
-rwxr-xr-xoctoprintApis/SelectFileRequest.go50
-rwxr-xr-xoctoprintApis/StartRequest.go26
-rwxr-xr-xoctoprintApis/StatusMapping.go23
-rwxr-xr-xoctoprintApis/TemperatureDataRequest.go66
-rwxr-xr-xoctoprintApis/ToolExtrudeRequest.go41
-rwxr-xr-xoctoprintApis/ToolFlowRateRequest.go39
-rwxr-xr-xoctoprintApis/ToolOffsetRequest.go40
-rwxr-xr-xoctoprintApis/ToolSelectRequest.go40
-rwxr-xr-xoctoprintApis/ToolStateRequest.go60
-rwxr-xr-xoctoprintApis/ToolTargetRequest.go40
-rwxr-xr-xoctoprintApis/UploadFileRequest.go92
-rwxr-xr-xoctoprintApis/ZOffsetRequest.go64
-rwxr-xr-xoctoprintApis/_examples/state/main.go40
-rwxr-xr-xoctoprintApis/client.go158
-rwxr-xr-xoctoprintApis/common.go3
-rwxr-xr-xoctoprintApis/common_test.go178
-rwxr-xr-xoctoprintApis/connection.go17
-rwxr-xr-xoctoprintApis/dataModels/ApiConfig.go11
-rwxr-xr-xoctoprintApis/dataModels/Axis.go10
-rwxr-xr-xoctoprintApis/dataModels/CommandDefinition.go38
-rwxr-xr-xoctoprintApis/dataModels/CommandSource.go13
-rwxr-xr-xoctoprintApis/dataModels/ConnectionResponse.go43
-rwxr-xr-xoctoprintApis/dataModels/ConnectionState.go45
-rwxr-xr-xoctoprintApis/dataModels/ControlContainer.go23
-rwxr-xr-xoctoprintApis/dataModels/ControlDefinition.go79
-rwxr-xr-xoctoprintApis/dataModels/ControlInput.go29
-rwxr-xr-xoctoprintApis/dataModels/CustomCommandsResponse.go7
-rwxr-xr-xoctoprintApis/dataModels/FeaturesConfig.go86
-rwxr-xr-xoctoprintApis/dataModels/Filament.go10
-rwxr-xr-xoctoprintApis/dataModels/FileResponse.go90
-rwxr-xr-xoctoprintApis/dataModels/FilesResponse.go16
-rwxr-xr-xoctoprintApis/dataModels/FolderConfig.go29
-rwxr-xr-xoctoprintApis/dataModels/FullStateResponse.go13
-rwxr-xr-xoctoprintApis/dataModels/GCodeAnalysisInformation.go10
-rwxr-xr-xoctoprintApis/dataModels/HistoricTemperatureData.go38
-rwxr-xr-xoctoprintApis/dataModels/JobInformation.go34
-rwxr-xr-xoctoprintApis/dataModels/JobResponse.go19
-rwxr-xr-xoctoprintApis/dataModels/JsonTime.go29
-rwxr-xr-xoctoprintApis/dataModels/Location.go10
-rwxr-xr-xoctoprintApis/dataModels/MenuItem.go9
-rwxr-xr-xoctoprintApis/dataModels/NotificationResponse.go7
-rwxr-xr-xoctoprintApis/dataModels/OctoScreenSettingsResponse.go16
-rwxr-xr-xoctoprintApis/dataModels/PauseAction.go15
-rwxr-xr-xoctoprintApis/dataModels/Plugin.go28
-rwxr-xr-xoctoprintApis/dataModels/PluginManagerInfoResponse.go12
-rwxr-xr-xoctoprintApis/dataModels/PrintStats.go20
-rwxr-xr-xoctoprintApis/dataModels/PrinterProfileResponse.go20
-rwxr-xr-xoctoprintApis/dataModels/PrinterProfilesResponse.go6
-rwxr-xr-xoctoprintApis/dataModels/PrinterState.go16
-rwxr-xr-xoctoprintApis/dataModels/Profile.go10
-rwxr-xr-xoctoprintApis/dataModels/ProgressInformation.go30
-rwxr-xr-xoctoprintApis/dataModels/Reference.go16
-rwxr-xr-xoctoprintApis/dataModels/SdState.go7
-rwxr-xr-xoctoprintApis/dataModels/SerialConfig.go102
-rwxr-xr-xoctoprintApis/dataModels/ServerConfig.go58
-rwxr-xr-xoctoprintApis/dataModels/SettingsResponse.go35
-rwxr-xr-xoctoprintApis/dataModels/SystemCommandsResponse.go8
-rwxr-xr-xoctoprintApis/dataModels/TemperatureConfig.go21
-rwxr-xr-xoctoprintApis/dataModels/TemperatureData.go22
-rwxr-xr-xoctoprintApis/dataModels/TemperatureDataResponse.go13
-rwxr-xr-xoctoprintApis/dataModels/TemperaturePreset.go9
-rwxr-xr-xoctoprintApis/dataModels/TemperatureStateResponse.go45
-rwxr-xr-xoctoprintApis/dataModels/TerminalFilter.go9
-rwxr-xr-xoctoprintApis/dataModels/UploadFileResponse.go25
-rwxr-xr-xoctoprintApis/dataModels/VersionResponse.go12
-rwxr-xr-xoctoprintApis/dataModels/WebcamConfig.go41
-rwxr-xr-xoctoprintApis/dataModels/ZOffsetResponse.go7
-rwxr-xr-xoctoprintApis/files.go41
-rwxr-xr-xoctoprintApis/job.go16
-rwxr-xr-xoctoprintApis/printer.go64
-rwxr-xr-xoctoprintApis/settings.go29
-rwxr-xr-xoctoprintApis/system.go73
-rwxr-xr-xoctoprintApis/system_test.go33
-rwxr-xr-xoctoprintApis/version.go29
-rwxr-xr-xoctoprintApis/zbolt.go11
-rwxr-xr-xstyles/z-bolt/images/blank.svg6
-rw-r--r--styles/z-bolt/images/extruder-typeB-1.svg40
-rw-r--r--styles/z-bolt/images/extruder-typeB-2.svg40
-rw-r--r--styles/z-bolt/images/extruder-typeB-3.svg40
-rw-r--r--styles/z-bolt/images/extruder-typeB-4.svg40
-rw-r--r--styles/z-bolt/images/extruder-typeB.svg34
-rwxr-xr-xstyles/z-bolt/images/file-gcode.svg110
-rwxr-xr-xstyles/z-bolt/images/file-stl.svg81
-rwxr-xr-xstyles/z-bolt/images/octoprint-tentacle.svg20
-rwxr-xr-x[-rw-r--r--]styles/z-bolt/images/open.svg23
-rw-r--r--styles/z-bolt/images/sd-eject.svg190
-rwxr-xr-x[-rw-r--r--]styles/z-bolt/images/sd.svg135
-rw-r--r--styles/z-bolt/images/speed-0%.svg45
-rw-r--r--styles/z-bolt/images/speed-100%.svg45
-rw-r--r--styles/z-bolt/images/speed-17%.svg45
-rw-r--r--styles/z-bolt/images/speed-34%.svg45
-rw-r--r--styles/z-bolt/images/speed-50%.svg45
-rw-r--r--styles/z-bolt/images/speed-67%.svg45
-rw-r--r--styles/z-bolt/images/speed-83%.svg45
-rw-r--r--styles/z-bolt/images/z-calibration.svg120
-rw-r--r--styles/z-bolt/images/z-offset-decrease.svg4
-rw-r--r--styles/z-bolt/images/z-offset-increase.svg4
-rwxr-xr-xstyles/z-bolt/style.css63
-rwxr-xr-xui/BedLevelPanel.go36
-rwxr-xr-xui/CommonPanel.go9
-rwxr-xr-xui/ConnectionPanel.go2
-rwxr-xr-xui/ControlPanel.go30
-rwxr-xr-xui/CustomItemsPanel.go7
-rwxr-xr-xui/FanPanel.go1
-rwxr-xr-xui/FatalErrorWindow.go7
-rwxr-xr-xui/FilamentPanel.go25
-rwxr-xr-xui/FilesPanel.go571
-rwxr-xr-xui/HomePanel.go9
-rwxr-xr-xui/HttpRequestTestWindow.go144
-rwxr-xr-xui/IdleStatusPanel.go61
-rwxr-xr-xui/LocationHistory.go40
-rwxr-xr-xui/MovePanel.go27
-rwxr-xr-xui/NetworkPanel.go9
-rwxr-xr-xui/PrintStatusPanel.go64
-rwxr-xr-xui/SplashPanel.go32
-rwxr-xr-xui/SystemPanel.go2
-rwxr-xr-xui/TemperaturePanel.go12
-rwxr-xr-xui/TemperaturePresetsPanel.go23
-rwxr-xr-xui/menu.go39
-rwxr-xr-xui/tool_changer_panel.go22
-rwxr-xr-xui/ui.go350
-rwxr-xr-xui/z_offset_calibration_panel.go42
-rwxr-xr-xuiWidgets/AmountToExtrudeStepButton.go2
-rwxr-xr-xuiWidgets/AmountToMoveStepButton.go2
-rwxr-xr-xuiWidgets/CommandButton.go28
-rwxr-xr-xuiWidgets/ControlButton.go27
-rwxr-xr-xuiWidgets/CoolDownButton.go30
-rwxr-xr-xuiWidgets/FanButton.go13
-rwxr-xr-xuiWidgets/FilamentExtrudeButton.go58
-rwxr-xr-xuiWidgets/FilamentLoadButton.go58
-rwxr-xr-xuiWidgets/FlowRateStepButton.go20
-rwxr-xr-xuiWidgets/HomeAllButton.go25
-rwxr-xr-xuiWidgets/HomeButton.go19
-rwxr-xr-xuiWidgets/IncreaseZOffsetButton.go1
-rwxr-xr-xuiWidgets/ManualZCalibrationStepButton.go2
-rwxr-xr-xuiWidgets/MoveButton.go23
-rwxr-xr-xuiWidgets/MustPressedButton.go8
-rwxr-xr-xuiWidgets/OctoPrintInfoBox.go22
-rwxr-xr-xuiWidgets/OctoScreenInfoBox.go5
-rwxr-xr-xuiWidgets/OctoScreenPluginInfoBox.go38
-rwxr-xr-xuiWidgets/SelectToolStepButton.go86
-rwxr-xr-xuiWidgets/StepButton.go2
-rwxr-xr-xuiWidgets/SystemCommandButton.go17
-rwxr-xr-xuiWidgets/SystemInfoBox.go8
-rwxr-xr-xuiWidgets/SystemInformationInfoBox.go5
-rwxr-xr-xuiWidgets/TemperatureAmountStepButton.go2
-rwxr-xr-xuiWidgets/TemperatureIncreaseButton.go23
-rwxr-xr-xuiWidgets/TemperaturePresetButton.go55
-rwxr-xr-xuiWidgets/TemperatureStatusBox.go18
-rwxr-xr-xuiWidgets/ToolButton.go25
-rwxr-xr-xuiWidgets/ToolPrintingButon.go1
-rwxr-xr-xutils/BackgroundTask.go (renamed from utils/background_task.go)8
-rwxr-xr-xutils/FileResponsesSortedByDate.go25
-rwxr-xr-xutils/FileResponsesSortedByName.go26
-rwxr-xr-xutils/LocationHistory.go46
-rwxr-xr-xutils/UpdateTemperaturesBackgroundTask.go38
-rwxr-xr-xutils/environment.go64
-rwxr-xr-xutils/filament.go72
-rwxr-xr-xutils/file_utils.go (renamed from utils/file.go)23
-rwxr-xr-xutils/gtk.go84
-rwxr-xr-xutils/logger.go98
-rwxr-xr-xutils/string_utils.go37
-rwxr-xr-xutils/tools.go196
-rwxr-xr-xutils/ui_utils.go29
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/FileRequest.go138
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/FullStateRequest.go94
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/JobInformation.go33
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/JobRequest.go46
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/ProgressInformation.go29
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/SelectFileRequest.go48
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/TemperatureData.go21
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/TemperatureStateResponse.go47
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/client.go16
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/common.go257
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/connection.go2
-rwxr-xr-x[-rw-r--r--]vendor/github.com/mcuadros/go-octoprint/files.go141
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/job.go39
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/printer.go180
-rwxr-xr-xvendor/github.com/mcuadros/go-octoprint/system.go2
216 files changed, 7863 insertions, 1814 deletions
diff --git a/Makefile b/Makefile
index c57acba..40509c7 100644..100755
--- 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)
diff --git a/debian/octoscreen.service b/debian/octoscreen.service
index 7cbb15a..6391ef1 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/docs/ButtonImages.html b/docs/ButtonImages.html
index 1434799..789e8a8 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 @@
<img src="../styles/z-bolt/images/extruder.svg" />
<div>extruder</div>
+
+ <img src="../styles/z-bolt/images/extruder-typeB.svg" />
+ <div>extruder-typeB</div>
+
+ <img src="../styles/z-bolt/images/extruder-typeB-1.svg" />
+ <div>extruder-typeB-1</div>
+
+ <img src="../styles/z-bolt/images/extruder-typeB-2.svg" />
+ <div>extruder-typeB-2</div>
+
+ <img src="../styles/z-bolt/images/extruder-typeB-3.svg" />
+ <div>extruder-typeB-3</div>
+
+ <img src="../styles/z-bolt/images/extruder-typeB-4.svg" />
+ <div>extruder-typeB-4</div>
+
+
<img src="../styles/z-bolt/images/fan-off.svg" />
<div>fan-off</div>
@@ -83,6 +101,9 @@
<img src="../styles/z-bolt/images/filament-spool.svg" />
<div>filament-spool</div>
+ <img src="../styles/z-bolt/images/file-gcode.svg" />
+ <div>file-gcode</div>
+
<img src="../styles/z-bolt/images/file-stl.svg" />
<div>file-stl</div>
@@ -182,6 +203,9 @@
<img src="../styles/z-bolt/images/nozzle.svg" />
<div>nozzle</div>
+ <img src="../styles/z-bolt/images/octoprint-tentacle.svg" />
+ <div>octoprint-tentacle</div>
+
<img src="../styles/z-bolt/images/open.svg" />
<div>open</div>
@@ -221,6 +245,27 @@
<img src="../styles/z-bolt/images/shutdown.svg" />
<div>shutdown</div>
+ <img src="../styles/z-bolt/images/speed-0%.svg" />
+ <div>speed-0%</div>
+
+ <img src="../styles/z-bolt/images/speed-17%.svg" />
+ <div>speed-17%</div>
+
+ <img src="../styles/z-bolt/images/speed-34%.svg" />
+ <div>speed-34%</div>
+
+ <img src="../styles/z-bolt/images/speed-50%.svg" />
+ <div>speed-50%</div>
+
+ <img src="../styles/z-bolt/images/speed-67%.svg" />
+ <div>speed-67%</div>
+
+ <img src="../styles/z-bolt/images/speed-83%.svg" />
+ <div>speed-83%</div>
+
+ <img src="../styles/z-bolt/images/speed-100%.svg" />
+ <div>speed-100%</div>
+
<img src="../styles/z-bolt/images/speed-fast.svg" />
<div>speed-fast</div>
diff --git a/interfaces/ITemperatureDataDisplay.go b/interfaces/ITemperatureDataDisplay.go
index 2ae6436..adca6fe 100755
--- a/interfaces/ITemperatureDataDisplay.go
+++ b/interfaces/ITemperatureDataDisplay.go
@@ -1,9 +1,10 @@
package interfaces
import (
- "github.com/mcuadros/go-octoprint"
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
)
type ITemperatureDataDisplay interface {
- UpdateTemperatureData(temperatureData map[string]octoprint.TemperatureData)
+ UpdateTemperatureData(temperatureData map[string]dataModels.TemperatureData)
}
diff --git a/logger/contextHook.go b/logger/contextHook.go
new file mode 100755
index 0000000..fd86751
--- /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
new file mode 100755
index 0000000..910f6f2
--- /dev/null
+++ b/logger/logger.go
@@ -0,0 +1,186 @@
+package logger
+
+import (
+ "fmt"
+ "io"
+ standardLog "log"
+ "os"
+ // "path"
+ // "runtime"
+ "strings"
+ "sync"
+ // "time"
+
+ "github.com/sirupsen/logrus"
+)
+
+
+var _mutex *sync.RWMutex = nil
+var _indentLevel int = -1
+var _indentation string = ""
+const INDENTATION_TOKEN = " "
+const INDENTATION_TOKEN_LENGTH = 4
+
+var _logrusLogger *logrus.Logger
+var _logrusEntry *logrus.Entry
+var _logLevel logrus.Level
+var _strLogLevel string
+
+
+func init() {
+ _mutex = &sync.RWMutex {}
+
+ _indentLevel = 0
+ _indentation = ""
+
+ _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 == "" {
+ standardLog.Print("logger.init() - logFilePath is was not defined. Now using just the standard console output.")
+ _logrusLogger.Out = os.Stdout
+ } else {
+ 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 {
+ standardLog.Printf("logger.init() - OpenFile() succeeded and now setting log.Out to %s", logFilePath)
+ _logrusLogger.Out = file
+
+ _logrusLogger.Out = io.MultiWriter(os.Stdout, file)
+ logrus.SetOutput(_logrusLogger.Out)
+ } else {
+ 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
+ }
+ }
+
+ _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 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())
+
+ _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", readIndentation(), functionName)
+ _logrusEntry.Debug(message)
+ _indentLevel++
+ indentation := readIndentation() + INDENTATION_TOKEN
+ writeIndentation(indentation)
+}
+
+func TraceLeave(functionName string) {
+ _indentLevel--
+
+ 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", readIndentation(), currentFunctionName, functionCalledName, err)
+ } else {
+ _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", readIndentation(), currentFunctionName, functionCalledName, err)
+ } else {
+ _logrusEntry.Fatalf("%s%s - %s returned an error", readIndentation(), currentFunctionName, functionCalledName)
+ }
+}
+
+
+func Debug(args ...interface{}) {
+ _logrusEntry.Debug(readIndentation() + fmt.Sprint(args...))
+}
+
+func Debugf(format string, args ...interface{}) {
+ _logrusEntry.Debugf(readIndentation() + format, args...)
+}
+
+
+func Info(args ...interface{}) {
+ _logrusEntry.Info(readIndentation() + fmt.Sprint(args...))
+}
+
+func Infof(format string, args ...interface{}) {
+ _logrusEntry.Infof(readIndentation() + format, args...)
+}
+
+
+func Warn(args ...interface{}) {
+ _logrusEntry.Warn(readIndentation() + fmt.Sprint(args...))
+}
+
+func Warnf(format string, args ...interface{}) {
+ _logrusEntry.Warnf(readIndentation() + format, args...)
+}
+
+
+func Error(args ...interface{}) {
+ _logrusEntry.Error(readIndentation() + fmt.Sprint(args...))
+}
+
+func Errorf(format string, args ...interface{}) {
+ _logrusEntry.Errorf(readIndentation() + format, args...)
+}
+
+
+func Fatal(args ...interface{}) {
+ _logrusEntry.Fatal(readIndentation() + fmt.Sprint(args...))
+}
+
+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...)
+}
diff --git a/main.go b/main.go
index bc3d7cb..18a0ec3 100755
--- a/main.go
+++ b/main.go
@@ -1,58 +1,43 @@
package main
import (
+ "errors"
"fmt"
"io/ioutil"
standardLog "log"
"os"
"os/user"
"path/filepath"
+ "runtime"
"strconv"
"strings"
+ "github.com/gotk3/gotk3/gtk"
+ "github.com/sirupsen/logrus"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis"
"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"
+ "gopkg.in/yaml.v1"
)
+
var (
BaseURL string
APIKey string
ConfigFile string
Resolution string
+ initSucceeded bool
)
-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.TraceEnter("OctoScreen - main.init()")
+ initSucceeded = false
ConfigFile = os.Getenv(utils.EnvConfigFile)
if ConfigFile == "" {
@@ -60,46 +45,151 @@ func init() {
}
cfg := readConfig(ConfigFile)
- setApiKey(cfg)
-
- if !utils.RequiredEnvironmentVariablesAreSet(APIKey) {
- utils.Logger.Error("OctoScreen - main.init() - RequiredEnvironmentVariablesAreSet() returned false")
-
- utils.Logger.Debug("OctoScreen - leaving main.init()")
+ if cfg == nil {
+ initSucceeded = false
return
}
+ setApiKey(cfg)
setLogLevel()
-
utils.StylePath = os.Getenv(utils.EnvStylePath)
Resolution = os.Getenv(utils.EnvResolution)
setBaseUrl(cfg)
- utils.Logger.Debug("OctoScreen - leaving main.init()")
+ initSucceeded = true
+ logger.TraceLeave("OctoScreen - main.init()")
+ logger.Debug("-")
+ logger.Debug("-")
+}
+
+
+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()")
+
+ gtk.Init(nil)
+ settings, _ := gtk.SettingsGetDefault()
+ settings.SetProperty("gtk-application-prefer-dark-theme", true)
+
+ utils.DumpEnvironmentVariables()
+
+ 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()
+
+ logger.TraceLeave("OctoScreen - main.main()")
+ logger.Debug("+")
+ logger.Debug("+")
}
+
func setLogLevel() {
- logLevel := utils.LowerCaseLogLevel()
+ logLevel := strings.ToLower(os.Getenv(utils.EnvLogLevel))
+
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)
+ // 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)
@@ -116,32 +206,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()")
}
@@ -156,132 +245,126 @@ 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")
- return cfg
- } else {
- utils.Logger.Infof("Path to OctoPrint's config file: %q", configFile)
+ logger.Info("main.readConfig() - configFile is empty")
+ logger.TraceLeave("main.readConfig()")
+ return nil
}
+ 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)
- } else {
- utils.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 {
- utils.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.Errorf("main.readConfig() - error decoding YAML config file %q: %s", configFile, err)
+ logger.TraceLeave("main.readConfig()")
+ return nil
}
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()")
- 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")
+func getSize() (width int, height int, err error) {
+ logger.TraceEnter("main.getSize()")
- utils.Logger.Debug("leaving main.getSize()")
+ if Resolution == "" {
+ 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")
+ 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 {
- utils.LogError("main.getSize()", "Atoi(parts[0])", err)
- utils.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 {
- utils.LogError("main.getSize()", "Atoi(parts[1])", err)
- utils.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))
+ }
}
- utils.Logger.Debug("leaving main.getSize()")
+ logger.TraceLeave("main.getSize()")
return
}
diff --git a/octoprintApis/BedOffsetRequest.go b/octoprintApis/BedOffsetRequest.go
new file mode 100755
index 0000000..d0fff54
--- /dev/null
+++ b/octoprintApis/BedOffsetRequest.go
@@ -0,0 +1,39 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..893e9ad
--- /dev/null
+++ b/octoprintApis/BedStateRequest.go
@@ -0,0 +1,43 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ "fmt"
+ // "io"
+ // "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 0000000..64936ea
--- /dev/null
+++ b/octoprintApis/BedTargetRequest.go
@@ -0,0 +1,39 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..4b4ed19
--- /dev/null
+++ b/octoprintApis/CancelRequest.go
@@ -0,0 +1,26 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "io"
+
+ // "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 0000000..758a636
--- /dev/null
+++ b/octoprintApis/CommandRequest.go
@@ -0,0 +1,31 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ // "io"
+ // "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 0000000..2b7d2f2
--- /dev/null
+++ b/octoprintApis/ConnectRequest.go
@@ -0,0 +1,68 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ // "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(client *Client) error {
+ logger.TraceEnter("ConnectRequest.Do()")
+
+ bytes := bytes.NewBuffer(nil)
+ if err := cmd.encode(bytes); err != nil {
+ logger.LogError("ConnectRequest.Do()", "cmd.encode()", err)
+ logger.TraceLeave("ConnectRequest.Do()")
+ return err
+ }
+
+ _, err := client.doJsonRequest("POST", ConnectionApiUri, bytes, ConnectionErrors)
+ if err != nil {
+ logger.LogError("ConnectRequest.go()", "client.doJsonRequest(POST)", err)
+ }
+
+ logger.TraceLeave("ConnectRequest.Do()")
+ return err
+}
+
+func (cmd *ConnectRequest) encode(w io.Writer) error {
+ 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
new file mode 100755
index 0000000..49b4e15
--- /dev/null
+++ b/octoprintApis/ConnectionRequest.go
@@ -0,0 +1,38 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ // "io"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "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(client *Client) (*dataModels.ConnectionResponse, error) {
+ logger.TraceEnter("ConnectionRequest.Do()")
+
+ bytes, err := client.doJsonRequest("GET", ConnectionApiUri, nil, nil)
+ if err != nil {
+ 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 {
+ logger.LogError("ConnectionRequest.Do()", "json.Unmarshal()", err)
+ logger.TraceLeave("ConnectionRequest.Do()")
+ return nil, err
+ }
+
+ logger.TraceLeave("ConnectionRequest.Do()")
+ return response, err
+}
diff --git a/octoprintApis/CustomCommandsRequest.go b/octoprintApis/CustomCommandsRequest.go
new file mode 100755
index 0000000..485533b
--- /dev/null
+++ b/octoprintApis/CustomCommandsRequest.go
@@ -0,0 +1,30 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ // "fmt"
+ // "io"
+ // "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 0000000..0f033dc
--- /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 0000000..3cdf7b6
--- /dev/null
+++ b/octoprintApis/DisconnectRequest.go
@@ -0,0 +1,44 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ // "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 (this *DisconnectRequest) Do(client *Client) error {
+ logger.TraceEnter("DisconnectRequest.Do()")
+
+ bytes := bytes.NewBuffer(nil)
+ 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 {
+ logger.LogError("DisconnectRequest.Do()", "client.doJsonRequest(POST)", err)
+ }
+
+ logger.TraceLeave("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
new file mode 100755
index 0000000..939b1ae
--- /dev/null
+++ b/octoprintApis/FakesAckRequest.go
@@ -0,0 +1,49 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ // "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.
+//
+// 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 (this *FakesAckRequest) Do(client *Client) error {
+ logger.TraceEnter("FakesAckRequest.Do()")
+
+ bytes := bytes.NewBuffer(nil)
+ 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 {
+ logger.LogError("FakesAckRequest.Do()", "client.doJsonRequest(POST)", err)
+ logger.LogError("main.findConfigFile()", "Current()", err)
+ }
+
+ logger.TraceLeave("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/FileRequest.go b/octoprintApis/FileRequest.go
new file mode 100755
index 0000000..cc872b9
--- /dev/null
+++ b/octoprintApis/FileRequest.go
@@ -0,0 +1,53 @@
+//package apis
+package octoprintApis
+
+import (
+ "encoding/json"
+ "fmt"
+ // "strconv"
+ // "strings"
+ // "time"
+
+ "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 dataModels.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 (request *FileRequest) Do(c *Client) (*dataModels.FileResponse, error) {
+ uri := fmt.Sprintf("%s/%s/%s?recursive=%t",
+ FilesApiUri,
+ request.Location,
+ request.Filename,
+ request.Recursive,
+ )
+
+ bytes, err := c.doJsonRequest("GET", uri, nil, FilesLocationGETErrors)
+ if err != nil {
+ return nil, err
+ }
+
+ response := &dataModels.FileResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ return nil, err
+ }
+
+ return response, err
+}
diff --git a/octoprintApis/FilesRequest.go b/octoprintApis/FilesRequest.go
new file mode 100755
index 0000000..335fb2a
--- /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
new file mode 100755
index 0000000..f77f11b
--- /dev/null
+++ b/octoprintApis/FullStateRequest.go
@@ -0,0 +1,83 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ "fmt"
+ "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.
+ 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 *FullStateRequest) Do(c *Client) (*dataModels.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 := &dataModels.FullStateResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ return nil, err
+ }
+
+ return response, err
+}
diff --git a/octoprintApis/JobRequest.go b/octoprintApis/JobRequest.go
new file mode 100755
index 0000000..c8a6808
--- /dev/null
+++ b/octoprintApis/JobRequest.go
@@ -0,0 +1,29 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ // "io"
+
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+// 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(client *Client) (*dataModels.JobResponse, error) {
+ bytes, err := client.doJsonRequest("GET", JobApiUri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ response := &dataModels.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 100755
index 0000000..70377d0
--- /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/NotificationRequest.go b/octoprintApis/NotificationRequest.go
new file mode 100755
index 0000000..3da608d
--- /dev/null
+++ b/octoprintApis/NotificationRequest.go
@@ -0,0 +1,33 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ "fmt"
+
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+type NotificationRequest struct {
+ Command string `json:"command"`
+}
+
+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 := client.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 0000000..0ca8974
--- /dev/null
+++ b/octoprintApis/OctoScreenSettingsRequest.go
@@ -0,0 +1,31 @@
+package octoprintApis
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "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 (this *OctoScreenSettingsRequest) Do(client *Client, uiState string) (*dataModels.OctoScreenSettingsResponse, error) {
+ target := fmt.Sprintf("%s?command=get_settings", PluginZBoltOctoScreenApiUri)
+ bytes, err := client.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 0000000..e4b97eb
--- /dev/null
+++ b/octoprintApis/PauseRequest.go
@@ -0,0 +1,40 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+
+ "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 0000000..8d93abd
--- /dev/null
+++ b/octoprintApis/PluginManagerInfoRequest.go
@@ -0,0 +1,42 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+const pluginManagerRequestURI = "/api/plugin/pluginmanager"
+
+// PluginManagerInfoRequest -
+type PluginManagerInfoRequest struct {
+ Command string `json:"command"`
+}
+
+// Do -
+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(this); err != nil {
+ logger.LogError("PluginManagerInfoRequest.Do()", "json.NewEncoder(params).Encode(this)", err)
+ return nil, err
+ }
+
+ bytes, err := client.doJsonRequest("GET", pluginManagerRequestURI, params, ConnectionErrors)
+ if err != nil {
+ logger.LogError("PluginManagerInfoRequest.Do()", "client.doJsonRequest()", err)
+ return nil, err
+ }
+
+ response := &dataModels.PluginManagerInfoResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ logger.LogError("PluginManagerInfoRequest.Do()", "json.Unmarshal()", err)
+ return nil, err
+ }
+
+ return response, err
+}
diff --git a/octoprintApis/PrintHeadHomeRequest.go b/octoprintApis/PrintHeadHomeRequest.go
new file mode 100755
index 0000000..2a67767
--- /dev/null
+++ b/octoprintApis/PrintHeadHomeRequest.go
@@ -0,0 +1,39 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..bd4b93e
--- /dev/null
+++ b/octoprintApis/PrintHeadJogRequest.go
@@ -0,0 +1,59 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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
new file mode 100755
index 0000000..675f5ba
--- /dev/null
+++ b/octoprintApis/PrinterProfilesRequest.go
@@ -0,0 +1,30 @@
+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) (*dataModels.PrinterProfileResponse, error) {
+ uri := fmt.Sprintf("/api/printerprofiles/%s", cmd.Id)
+ b, err := c.doJsonRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ r := &dataModels.PrinterProfileResponse{}
+ if err := json.Unmarshal(b, r); err != nil {
+ return nil, err
+ }
+
+ return r, err
+}
diff --git a/octoprintApis/README.md b/octoprintApis/README.md
new file mode 100755
index 0000000..771e630
--- /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("<octoprint-url>", "<api-key>")
+
+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/<location>`
+- [x] POST `/api/files/<location>`
+- [x] GET `/api/files/<location>/<filename>`
+- [x] POST `/api/files/<location>/<path>` (Only select command)
+- [x] DELETE `/api/files/<location>/<path>`
+
+### [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/<locale>/<pack>`
+
+### [Log file management](http://docs.octoprint.org/en/master/api/logs.html)
+- [ ] GET `/api/logs`
+- [ ] DELETE `/api/logs/<filename>`
+
+### [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/<profile>`
+- [ ] DELETE `/api/printerprofiles/<profile>`
+
+### [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/<slicer>/profiles`
+- [ ] GET `/api/slicing/<slicer>/profiles/<key>`
+- [ ] PUT `/api/slicing/<slicer>/profiles/<key>`
+- [ ] DELETE `/api/slicing/<slicer>/profiles/<key>`
+
+### [System](http://docs.octoprint.org/en/master/api/system.html)
+- [x] GET `/api/system/commands`
+- [ ] GET `/api/system/commands/<source>`
+- [x] POST `/api/system/commands/<source>/<action>`
+
+### [Timelapse](http://docs.octoprint.org/en/master/api/timelapse.html)
+- [ ] GET `/api/timelapse`
+- [ ] DELETE `/api/timelapse/<filename>`
+- [ ] POST `/api/timelapse/unrendered/<name>`
+- [ ] DELETE `/api/timelapse/unrendered/<name>`
+- [ ] POST `/api/timelapse`
+
+### [User](http://docs.octoprint.org/en/master/api/users.html)
+- [ ] GET `/api/users`
+- [ ] GET `/api/users/<username>`
+- [ ] POST `/api/users`
+- [ ] PUT `/api/users/<username>`
+- [ ] DELETE `/api/users/<username>`
+- [ ] PUT `/api/users/<username>/password`
+- [ ] GET `/api/users/<username>/settings`
+- [ ] PATCH `/api/users/<username>/settings`
+- [ ] POST `/api/users/<username>/apikey`
+- [ ] DELETE `/api/users/<username>/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/RestartRequest.go b/octoprintApis/RestartRequest.go
new file mode 100755
index 0000000..df117ce
--- /dev/null
+++ b/octoprintApis/RestartRequest.go
@@ -0,0 +1,28 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "io"
+
+ // "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 0000000..18d9d46
--- /dev/null
+++ b/octoprintApis/RunZOffsetCalibrationRequest.go
@@ -0,0 +1,27 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+)
+
+
+type RunZOffsetCalibrationRequest struct {
+ Command string `json:"command"`
+}
+
+func (this *RunZOffsetCalibrationRequest) Do(client *Client) error {
+ this.Command = "run_zoffset_calibration"
+
+ 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 := client.doJsonRequest("POST", PluginZBoltOctoScreenApiUri, bytes, ConnectionErrors)
+ return err
+}
diff --git a/octoprintApis/SdInitRequest.go b/octoprintApis/SdInitRequest.go
new file mode 100755
index 0000000..fcfe212
--- /dev/null
+++ b/octoprintApis/SdInitRequest.go
@@ -0,0 +1,22 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "fmt"
+ // "io"
+ // "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 0000000..92c6dbf
--- /dev/null
+++ b/octoprintApis/SdRefreshRequest.go
@@ -0,0 +1,20 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "fmt"
+ // "io"
+ // "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 0000000..d7a1b4a
--- /dev/null
+++ b/octoprintApis/SdReleaseRequest.go
@@ -0,0 +1,22 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "fmt"
+ // "io"
+ // "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 0000000..87c8717
--- /dev/null
+++ b/octoprintApis/SdStateRequest.go
@@ -0,0 +1,31 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ // "fmt"
+ // "io"
+ // "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
new file mode 100755
index 0000000..7e50289
--- /dev/null
+++ b/octoprintApis/SelectFileRequest.go
@@ -0,0 +1,50 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+
+ "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 dataModels.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", FilesApiUri, 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/StartRequest.go b/octoprintApis/StartRequest.go
new file mode 100755
index 0000000..b1a7638
--- /dev/null
+++ b/octoprintApis/StartRequest.go
@@ -0,0 +1,26 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "io"
+
+ // "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 0000000..d49ed4b
--- /dev/null
+++ b/octoprintApis/StatusMapping.go
@@ -0,0 +1,23 @@
+package octoprintApis
+
+import (
+ // "errors"
+ "fmt"
+ // "io"
+ // "io/ioutil"
+ // "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 0000000..2bca238
--- /dev/null
+++ b/octoprintApis/TemperatureDataRequest.go
@@ -0,0 +1,66 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ "fmt"
+ // "io"
+ // "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 0000000..58942bf
--- /dev/null
+++ b/octoprintApis/ToolExtrudeRequest.go
@@ -0,0 +1,41 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..804ea5f
--- /dev/null
+++ b/octoprintApis/ToolFlowRateRequest.go
@@ -0,0 +1,39 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..0ae6aa5
--- /dev/null
+++ b/octoprintApis/ToolOffsetRequest.go
@@ -0,0 +1,40 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..2451457
--- /dev/null
+++ b/octoprintApis/ToolSelectRequest.go
@@ -0,0 +1,40 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..b491344
--- /dev/null
+++ b/octoprintApis/ToolStateRequest.go
@@ -0,0 +1,60 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ "encoding/json"
+ "fmt"
+ // "io"
+ // "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 0000000..34678c0
--- /dev/null
+++ b/octoprintApis/ToolTargetRequest.go
@@ -0,0 +1,40 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ "io"
+ // "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 0000000..2b3a581
--- /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 0000000..bd456dc
--- /dev/null
+++ b/octoprintApis/ZOffsetRequest.go
@@ -0,0 +1,64 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+type ZOffsetRequest struct {
+ Command string `json:"command"`
+ Tool int `json:"tool"`
+}
+
+func (this *ZOffsetRequest) Do(client *Client) (*dataModels.ZOffsetResponse, error) {
+ this.Command = "get_z_offset"
+
+ params := bytes.NewBuffer(nil)
+ if err := json.NewEncoder(params).Encode(this); err != nil {
+ logger.LogError("ZOffsetRequest.Do()", "json.NewEncoder(params).Encode(this)", err)
+ return nil, err
+ }
+
+ // b, err := client.doJsonRequest("POST", URIZBoltRequest, params, ConnectionErrors)
+ bytes, err := client.doJsonRequest("GET", PluginZBoltApiUri, params, ConnectionErrors)
+ if err != nil {
+ logger.LogError("ZOffsetRequest.Do()", "client.doJsonRequest()", err)
+ return nil, err
+ }
+
+ response := &dataModels.ZOffsetResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ logger.LogError("ZOffsetRequest.Do()", "json.Unmarshal()", err)
+ return nil, err
+ }
+
+ return response, err
+}
+
+
+
+
+// SetZOffsetRequest - retrieves the current configuration of OctoPrint.
+type SetZOffsetRequest struct {
+ Command string `json:"command"`
+ Tool int `json:"tool"`
+ Value float64 `json:"value"`
+}
+
+func (this *SetZOffsetRequest) Do(client *Client) error {
+ this.Command = "set_z_offset"
+
+ 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 := client.doJsonRequest("POST", PluginZBoltApiUri, bytes, ConnectionErrors)
+ return err
+}
diff --git a/octoprintApis/_examples/state/main.go b/octoprintApis/_examples/state/main.go
new file mode 100755
index 0000000..376c023
--- /dev/null
+++ b/octoprintApis/_examples/state/main.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/mgutz/logxi/v1"
+)
+
+func main() {
+ baseURL, apiKey := os.Args[1], os.Args[2]
+
+ c := octoprint.NewClient(baseURL, apiKey)
+ printConnectionState(c)
+ printTemperature(c)
+}
+
+func printConnectionState(c *octoprint.Client) {
+ r := octoprint.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 *octoprint.Client) {
+ 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)
+ }
+}
diff --git a/octoprintApis/client.go b/octoprintApis/client.go
new file mode 100755
index 0000000..9fed945
--- /dev/null
+++ b/octoprintApis/client.go
@@ -0,0 +1,158 @@
+package octoprintApis
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ // "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.
+ Endpoint string
+
+ // APIKey used to connect to the OctoPrint REST API server.
+ APIKey string
+
+ // HTTP client connection.
+ httpClient *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,
+ httpClient: &http.Client {
+ Timeout: time.Second * 3,
+ Transport: &http.Transport {
+ DisableKeepAlives: true,
+ },
+ },
+ }
+}
+
+func (this *Client) doJsonRequest(
+ method string,
+ target string,
+ body io.Reader,
+ statusMapping StatusMapping,
+) ([]byte, error) {
+ logger.TraceEnter("Client.doJsonRequest()")
+
+ bytes, err := this.doRequest(method, target, "application/json", body, statusMapping)
+ if err != nil {
+ logger.LogError("Client.doJsonRequest()", "this.doRequest()", err)
+ logger.TraceLeave("Client.doJsonRequest()")
+ return nil, err
+ }
+
+ // 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
+}
+
+func (this *Client) doRequest(
+ method string,
+ target string,
+ contentType string,
+ body io.Reader,
+ statusMapping StatusMapping,
+) ([]byte, error) {
+ 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 {
+ logger.LogError("Client.doRequest()", "http.NewRequest()", err)
+ logger.TraceLeave("Client.doRequest()")
+ 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", this.APIKey)
+ resp, err := this.httpClient.Do(req)
+ if err != nil {
+ logger.LogError("Client.doRequest()", "this.httpClient.Do()", err)
+ logger.TraceLeave("Client.doRequest()")
+ return nil, err
+ }
+
+ response, err := this.handleResponse(resp, statusMapping)
+ if err != nil {
+ logger.LogError("Client.doRequest()", "this.handleResponse()", err)
+ logger.TraceLeave("Client.doRequest()")
+ return nil, err
+ }
+
+ logger.TraceLeave("Client.doRequest()")
+ return response, err
+}
+
+
+func (this *Client) handleResponse(
+ httpResponse *http.Response,
+ statusMapping StatusMapping,
+) ([]byte, error) {
+ defer httpResponse.Body.Close()
+
+ if statusMapping != nil {
+ if err := statusMapping.Error(httpResponse.StatusCode); err != nil {
+ return nil, err
+ }
+ }
+
+ if httpResponse.StatusCode == 401 {
+ return nil, ErrUnauthorized
+ }
+
+ if httpResponse.StatusCode == 204 {
+ return nil, nil
+ }
+
+ body, err := ioutil.ReadAll(httpResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ if httpResponse.StatusCode >= 200 && httpResponse.StatusCode <= 209 {
+ return body, nil
+ }
+
+ return nil, fmt.Errorf("unexpected status code: %d", httpResponse.StatusCode)
+}
+
+
+func joinUrl(base, uri string) string {
+ u, _ := url.Parse(uri)
+ b, _ := url.Parse(base)
+ return b.ResolveReference(u).String()
+}
diff --git a/octoprintApis/common.go b/octoprintApis/common.go
new file mode 100755
index 0000000..0679367
--- /dev/null
+++ b/octoprintApis/common.go
@@ -0,0 +1,3 @@
+package octoprintApis
+
+var Version = "0.1"
diff --git a/octoprintApis/common_test.go b/octoprintApis/common_test.go
new file mode 100755
index 0000000..1db0f71
--- /dev/null
+++ b/octoprintApis/common_test.go
@@ -0,0 +1,178 @@
+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)
+}
+*/ \ No newline at end of file
diff --git a/octoprintApis/connection.go b/octoprintApis/connection.go
new file mode 100755
index 0000000..55c1bb3
--- /dev/null
+++ b/octoprintApis/connection.go
@@ -0,0 +1,17 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "io"
+
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+const ConnectionApiUri = "/api/connection"
+
+
+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 0000000..e205531
--- /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 0000000..55d48c0
--- /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 0000000..07aa5f7
--- /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 0000000..91d197b
--- /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 0000000..4fe7a83
--- /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 0000000..f2d94a8
--- /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 0000000..0a968a9
--- /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 0000000..e067332
--- /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<temperature>\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 0000000..9d03a78
--- /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 0000000..76e1553
--- /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 0000000..a39515b
--- /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:<temperature>` 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 0000000..359e743
--- /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 0000000..8b8d9c7
--- /dev/null
+++ b/octoprintApis/dataModels/FileResponse.go
@@ -0,0 +1,90 @@
+package dataModels
+
+import (
+ // "encoding/json"
+ // "fmt"
+ // "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 or the Cura Thumbnails plug-in
+ // is required for 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 0000000..aa88a5e
--- /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 0000000..447b5f2
--- /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 0000000..ee161f8
--- /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 0000000..5512927
--- /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 0000000..7bc87e3
--- /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/dataModels/JobInformation.go b/octoprintApis/dataModels/JobInformation.go
new file mode 100755
index 0000000..ff067c1
--- /dev/null
+++ b/octoprintApis/dataModels/JobInformation.go
@@ -0,0 +1,34 @@
+package dataModels
+
+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/dataModels/JobResponse.go b/octoprintApis/dataModels/JobResponse.go
new file mode 100755
index 0000000..2e7e6af
--- /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 0000000..c92b169
--- /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 0000000..262960b
--- /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 0000000..d7d24f6
--- /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 0000000..ecb64fa
--- /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 0000000..08842a4
--- /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 0000000..66ae447
--- /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 0000000..316020c
--- /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 0000000..be950f4
--- /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 0000000..2e08b8e
--- /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 0000000..337c892
--- /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 0000000..79f1b7f
--- /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 0000000..915d795
--- /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 0000000..cdbef84
--- /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/dataModels/ProgressInformation.go b/octoprintApis/dataModels/ProgressInformation.go
new file mode 100755
index 0000000..1d5ad5f
--- /dev/null
+++ b/octoprintApis/dataModels/ProgressInformation.go
@@ -0,0 +1,30 @@
+package dataModels
+
+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/dataModels/Reference.go b/octoprintApis/dataModels/Reference.go
new file mode 100755
index 0000000..d38c50e
--- /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 0000000..6121467
--- /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 0000000..b9dd694
--- /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 0000000..58f09d7
--- /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 0000000..c615873
--- /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 0000000..80a31cd
--- /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 0000000..03794f0
--- /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/dataModels/TemperatureData.go b/octoprintApis/dataModels/TemperatureData.go
new file mode 100755
index 0000000..aefba0e
--- /dev/null
+++ b/octoprintApis/dataModels/TemperatureData.go
@@ -0,0 +1,22 @@
+package dataModels
+
+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/dataModels/TemperatureDataResponse.go b/octoprintApis/dataModels/TemperatureDataResponse.go
new file mode 100755
index 0000000..a5febc7
--- /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 0000000..62e90f1
--- /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/dataModels/TemperatureStateResponse.go b/octoprintApis/dataModels/TemperatureStateResponse.go
new file mode 100755
index 0000000..5021e53
--- /dev/null
+++ b/octoprintApis/dataModels/TemperatureStateResponse.go
@@ -0,0 +1,45 @@
+package dataModels
+
+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/dataModels/TerminalFilter.go b/octoprintApis/dataModels/TerminalFilter.go
new file mode 100755
index 0000000..c541805
--- /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 0000000..6fdf8a5
--- /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 0000000..849f11d
--- /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 0000000..4af195a
--- /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 0000000..8ead603
--- /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
new file mode 100755
index 0000000..bfaa46b
--- /dev/null
+++ b/octoprintApis/files.go
@@ -0,0 +1,41 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "fmt"
+ // "io"
+ // "mime/multipart"
+
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+const FilesApiUri = "/api/files"
+
+
+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",
+ }
+)
diff --git a/octoprintApis/job.go b/octoprintApis/job.go
new file mode 100755
index 0000000..c6dbb4f
--- /dev/null
+++ b/octoprintApis/job.go
@@ -0,0 +1,16 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "io"
+)
+
+
+// https://docs.octoprint.org/en/master/api/job.html
+const JobApiUri = "/api/job"
+
+
+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/printer.go b/octoprintApis/printer.go
new file mode 100755
index 0000000..bf3ef79
--- /dev/null
+++ b/octoprintApis/printer.go
@@ -0,0 +1,64 @@
+package octoprintApis
+
+import (
+ "bytes"
+ "encoding/json"
+ // "fmt"
+ // "io"
+ // "strings"
+
+ // "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 {
+ 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.",
+ }
+)
+
+// 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}
+
+ buffer := bytes.NewBuffer(nil)
+ if err := json.NewEncoder(buffer).Encode(v); err != nil {
+ return err
+ }
+
+ _, err := client.doJsonRequest("POST", uri, buffer, statusMapping)
+
+ return err
+}
diff --git a/octoprintApis/settings.go b/octoprintApis/settings.go
new file mode 100755
index 0000000..c59b584
--- /dev/null
+++ b/octoprintApis/settings.go
@@ -0,0 +1,29 @@
+package octoprintApis
+
+import (
+ "encoding/json"
+
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+const SettingsApiUri = "/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) (*dataModels.SettingsResponse, error) {
+ bytes, err := c.doJsonRequest("GET", SettingsApiUri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ response := &dataModels.SettingsResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ return nil, err
+ }
+
+ return response, err
+}
diff --git a/octoprintApis/system.go b/octoprintApis/system.go
new file mode 100755
index 0000000..c879fdb
--- /dev/null
+++ b/octoprintApis/system.go
@@ -0,0 +1,73 @@
+package octoprintApis
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+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",
+}
+
+
+// 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) (*dataModels.SystemCommandsResponse, error) {
+ bytes, err := c.doJsonRequest("GET", SystemCommandsApiUri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ response := &dataModels.SystemCommandsResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ return nil, err
+ }
+
+ 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 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 response, err
+}
+
+// SystemExecuteCommandRequest retrieves all configured system commands.
+type SystemExecuteCommandRequest struct {
+ // Source for which to list commands.
+ Source dataModels.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", 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
new file mode 100755
index 0000000..0d6b633
--- /dev/null
+++ b/octoprintApis/system_test.go
@@ -0,0 +1,33 @@
+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)
+}
+*/ \ No newline at end of file
diff --git a/octoprintApis/version.go b/octoprintApis/version.go
new file mode 100755
index 0000000..d275f18
--- /dev/null
+++ b/octoprintApis/version.go
@@ -0,0 +1,29 @@
+package octoprintApis
+
+import (
+ "encoding/json"
+
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+)
+
+
+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) (*dataModels.VersionResponse, error) {
+ bytes, err := c.doJsonRequest("GET", VersionApiUri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ response := &dataModels.VersionResponse{}
+ if err := json.Unmarshal(bytes, response); err != nil {
+ return nil, err
+ }
+
+ return response, err
+}
diff --git a/octoprintApis/zbolt.go b/octoprintApis/zbolt.go
new file mode 100755
index 0000000..c6ca739
--- /dev/null
+++ b/octoprintApis/zbolt.go
@@ -0,0 +1,11 @@
+package octoprintApis
+
+import (
+ // "bytes"
+ // "encoding/json"
+ // "fmt"
+)
+
+
+const PluginZBoltApiUri = "/api/plugin/zbolt"
+const PluginZBoltOctoScreenApiUri = "/api/plugin/zbolt_octoscreen"
diff --git a/styles/z-bolt/images/blank.svg b/styles/z-bolt/images/blank.svg
new file mode 100755
index 0000000..f012b4b
--- /dev/null
+++ b/styles/z-bolt/images/blank.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="68px" height="68px" viewBox="-8.5 26.5 68 68" enable-background="new -8.5 26.5 68 68" xml:space="preserve">
+</svg>
diff --git a/styles/z-bolt/images/extruder-typeB-1.svg b/styles/z-bolt/images/extruder-typeB-1.svg
new file mode 100644
index 0000000..f0c0711
--- /dev/null
+++ b/styles/z-bolt/images/extruder-typeB-1.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Extruder">
+ <polygon id="Outline" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" points="52.184,51.391
+ 46.562,56.676 8.875,56.676 3.592,51.391 3.592,13.424 8.875,8.084 46.562,8.084 52.184,13.424 "/>
+
+ <circle id="Bearing" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" cx="39.736" cy="31.952" r="5.519"/>
+ <g id="Gear">
+ <path fill="#FCFAFA" d="M12.283,24.476c0.531,0.379,1.053,0.796,1.568,1.229c0.504-0.136,0.91-0.283,1.422-0.369
+ c0.243-0.04,0.583-0.021,0.717-0.096c0.24-0.137,0.4-0.614,0.546-0.861c0.188-0.316,0.336-0.587,0.495-0.874
+ c0.901-0.007,1.73,0.264,2.552,0.568c0.063,0.68,0.021,1.328,0.066,2.004c0.567,0.396,1.146,0.741,1.649,1.362
+ c0.674-0.044,1.388-0.238,2.06-0.283c0.54,0.703,0.897,1.601,1.11,2.311c-0.454,0.436-1.004,0.845-1.492,1.271
+ c0.021,0.771,0.112,1.564-0.04,2.293c0.234,0.229,0.487,0.418,0.745,0.657c0.232,0.217,0.642,0.491,0.729,0.713
+ c0.124,0.308-0.275,0.911-0.4,1.188c-0.206,0.43-0.405,0.776-0.622,1.129c-0.692-0.062-1.341-0.288-2.028-0.373
+ c-0.536,0.48-1.016,0.978-1.782,1.394c-0.14,0.692-0.065,1.441-0.225,2.128c-0.853,0.352-1.645,0.484-2.416,0.531
+ c-0.343-0.612-0.607-1.2-0.955-1.811c-0.755-0.149-1.525-0.246-2.234-0.57c-0.626,0.391-1.187,0.796-1.761,1.198
+ c-0.326-0.181-0.641-0.41-0.992-0.696c-0.276-0.224-0.814-0.553-0.915-0.879c-0.069-0.225,0.276-0.77,0.38-0.991
+ c0.174-0.379,0.319-0.653,0.434-0.977c-0.412-0.687-0.804-1.367-0.909-1.971c-0.651-0.325-1.368-0.41-2.028-0.689
+ c-0.164-0.904-0.115-1.756,0.054-2.573c0.317-0.063,0.649-0.12,0.975-0.199c0.314-0.078,0.77-0.131,0.97-0.288
+ c0.152-0.119,0.237-0.544,0.355-0.797c0.22-0.474,0.363-0.802,0.755-1.208c-0.332-0.646-0.633-1.281-0.816-1.886
+ C10.74,25.483,11.441,24.962,12.283,24.476z"/>
+ <path fill="#020000" d="M16.41,28.673c1.741,0,3.156,1.413,3.156,3.155c0,1.746-1.415,3.16-3.156,3.16
+ c-1.745,0-3.159-1.414-3.159-3.16C13.251,30.086,14.665,28.673,16.41,28.673z"/>
+ </g>
+ <g id="Filament_path">
+ <rect id="Path" x="25.212" y="8.084" fill="#FFFDFD" width="6.874" height="48.591"/>
+ <rect id="Entry" x="21.134" y="3.477" display="none" fill="#FCFCFC" width="15.032" height="4.606"/>
+ <rect id="Exit" x="21.134" y="56.676" display="none" fill="#FCFCFC" width="15.032" height="4.607"/>
+ </g>
+</g>
+<g id="Circle">
+ <g id="circle_index" transform="translate(62.000000, 173.000000)">
+ <circle id="Oval_1_" fill="#FFFFFF" cx="-15.458" cy="-159.406" r="13.594"/>
+ <text transform="matrix(1 0 0 1 -20.2341 -153.5803)" fill="#010101" font-family="'ArialMT'" font-size="16.8307">1</text>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/extruder-typeB-2.svg b/styles/z-bolt/images/extruder-typeB-2.svg
new file mode 100644
index 0000000..0163a86
--- /dev/null
+++ b/styles/z-bolt/images/extruder-typeB-2.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Extruder">
+ <polygon id="Outline" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" points="52.184,51.391
+ 46.562,56.676 8.875,56.676 3.592,51.391 3.592,13.424 8.875,8.084 46.562,8.084 52.184,13.424 "/>
+
+ <circle id="Bearing" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" cx="39.736" cy="31.952" r="5.519"/>
+ <g id="Gear">
+ <path fill="#FCFAFA" d="M12.283,24.476c0.53,0.379,1.053,0.796,1.567,1.229c0.504-0.136,0.91-0.283,1.422-0.369
+ c0.243-0.04,0.583-0.021,0.718-0.096c0.239-0.137,0.399-0.614,0.546-0.861c0.188-0.315,0.336-0.587,0.495-0.874
+ c0.9-0.007,1.729,0.265,2.552,0.568c0.062,0.68,0.021,1.328,0.065,2.004c0.567,0.396,1.146,0.741,1.649,1.362
+ c0.674-0.044,1.388-0.238,2.06-0.283c0.54,0.703,0.897,1.601,1.11,2.311c-0.454,0.437-1.004,0.846-1.492,1.271
+ c0.021,0.771,0.112,1.563-0.04,2.293c0.234,0.229,0.487,0.418,0.745,0.657c0.232,0.217,0.643,0.491,0.729,0.713
+ c0.124,0.308-0.275,0.911-0.4,1.188c-0.206,0.431-0.405,0.776-0.622,1.129c-0.692-0.062-1.341-0.287-2.028-0.372
+ c-0.535,0.479-1.016,0.978-1.781,1.394c-0.141,0.692-0.065,1.441-0.226,2.128c-0.853,0.352-1.645,0.484-2.416,0.531
+ c-0.343-0.612-0.606-1.2-0.955-1.812c-0.755-0.148-1.524-0.246-2.233-0.569c-0.626,0.391-1.188,0.796-1.762,1.197
+ c-0.325-0.181-0.641-0.409-0.991-0.695c-0.276-0.225-0.814-0.554-0.915-0.879c-0.069-0.226,0.275-0.771,0.38-0.991
+ c0.174-0.379,0.318-0.653,0.434-0.978c-0.412-0.687-0.804-1.366-0.909-1.971c-0.65-0.325-1.367-0.41-2.027-0.688
+ c-0.164-0.904-0.115-1.757,0.054-2.573c0.317-0.063,0.649-0.12,0.975-0.199c0.314-0.078,0.771-0.131,0.971-0.288
+ c0.151-0.119,0.236-0.544,0.354-0.797c0.221-0.474,0.363-0.802,0.755-1.208c-0.332-0.646-0.633-1.281-0.815-1.886
+ C10.74,25.483,11.441,24.962,12.283,24.476z"/>
+ <path fill="#020000" d="M16.41,28.673c1.74,0,3.155,1.413,3.155,3.155c0,1.746-1.415,3.16-3.155,3.16
+ c-1.745,0-3.159-1.414-3.159-3.16C13.251,30.086,14.665,28.673,16.41,28.673z"/>
+ </g>
+ <g id="Filament_path">
+ <rect id="Path" x="25.212" y="8.084" fill="#FFFDFD" width="6.874" height="48.591"/>
+ <rect id="Entry" x="21.134" y="3.477" display="none" fill="#FCFCFC" width="15.032" height="4.605"/>
+ <rect id="Exit" x="21.134" y="56.676" display="none" fill="#FCFCFC" width="15.032" height="4.607"/>
+ </g>
+</g>
+<g id="Circle">
+ <g id="circle_index" transform="translate(62.000000, 173.000000)">
+ <circle id="Oval_1_" fill="#FFFFFF" cx="-15.458" cy="-159.406" r="13.594"/>
+ <text transform="matrix(1 0 0 1 -20.2341 -153.5803)" fill="#010101" font-family="'ArialMT'" font-size="16.8307">2</text>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/extruder-typeB-3.svg b/styles/z-bolt/images/extruder-typeB-3.svg
new file mode 100644
index 0000000..e527c81
--- /dev/null
+++ b/styles/z-bolt/images/extruder-typeB-3.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Extruder">
+ <polygon id="Outline" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" points="52.184,51.391
+ 46.562,56.676 8.875,56.676 3.592,51.391 3.592,13.424 8.875,8.084 46.562,8.084 52.184,13.424 "/>
+
+ <circle id="Bearing" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" cx="39.736" cy="31.952" r="5.519"/>
+ <g id="Gear">
+ <path fill="#FCFAFA" d="M12.283,24.476c0.53,0.379,1.053,0.796,1.567,1.229c0.504-0.136,0.91-0.283,1.422-0.369
+ c0.243-0.04,0.583-0.021,0.718-0.096c0.239-0.137,0.399-0.614,0.546-0.861c0.188-0.315,0.336-0.587,0.495-0.874
+ c0.9-0.007,1.729,0.265,2.552,0.568c0.062,0.68,0.021,1.328,0.065,2.004c0.567,0.396,1.146,0.741,1.649,1.362
+ c0.674-0.044,1.388-0.238,2.06-0.283c0.54,0.703,0.897,1.601,1.11,2.311c-0.454,0.437-1.004,0.846-1.492,1.271
+ c0.021,0.771,0.112,1.563-0.04,2.293c0.234,0.229,0.487,0.418,0.745,0.657c0.232,0.217,0.643,0.491,0.729,0.713
+ c0.124,0.308-0.275,0.911-0.4,1.188c-0.206,0.431-0.405,0.776-0.622,1.129c-0.692-0.062-1.341-0.287-2.028-0.372
+ c-0.535,0.479-1.016,0.978-1.781,1.394c-0.141,0.692-0.065,1.441-0.226,2.128c-0.853,0.352-1.645,0.484-2.416,0.531
+ c-0.343-0.612-0.606-1.2-0.955-1.812c-0.755-0.148-1.524-0.246-2.233-0.569c-0.626,0.391-1.188,0.796-1.762,1.197
+ c-0.325-0.181-0.641-0.409-0.991-0.695c-0.276-0.225-0.814-0.554-0.915-0.879c-0.069-0.226,0.275-0.771,0.38-0.991
+ c0.174-0.379,0.318-0.653,0.434-0.978c-0.412-0.687-0.804-1.366-0.909-1.971c-0.65-0.325-1.367-0.41-2.027-0.688
+ c-0.164-0.904-0.115-1.757,0.054-2.573c0.317-0.063,0.649-0.12,0.975-0.199c0.314-0.078,0.771-0.131,0.971-0.288
+ c0.151-0.119,0.236-0.544,0.354-0.797c0.221-0.474,0.363-0.802,0.755-1.208c-0.332-0.646-0.633-1.281-0.815-1.886
+ C10.74,25.483,11.441,24.962,12.283,24.476z"/>
+ <path fill="#020000" d="M16.41,28.673c1.74,0,3.155,1.413,3.155,3.155c0,1.746-1.415,3.16-3.155,3.16
+ c-1.745,0-3.159-1.414-3.159-3.16C13.251,30.086,14.665,28.673,16.41,28.673z"/>
+ </g>
+ <g id="Filament_path">
+ <rect id="Path" x="25.212" y="8.084" fill="#FFFDFD" width="6.874" height="48.591"/>
+ <rect id="Entry" x="21.134" y="3.477" display="none" fill="#FCFCFC" width="15.032" height="4.605"/>
+ <rect id="Exit" x="21.134" y="56.676" display="none" fill="#FCFCFC" width="15.032" height="4.607"/>
+ </g>
+</g>
+<g id="Circle">
+ <g id="circle_index" transform="translate(62.000000, 173.000000)">
+ <circle id="Oval_1_" fill="#FFFFFF" cx="-15.458" cy="-159.406" r="13.594"/>
+ <text transform="matrix(1 0 0 1 -20.2341 -153.5803)" fill="#010101" font-family="'ArialMT'" font-size="16.8307">3</text>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/extruder-typeB-4.svg b/styles/z-bolt/images/extruder-typeB-4.svg
new file mode 100644
index 0000000..0244d04
--- /dev/null
+++ b/styles/z-bolt/images/extruder-typeB-4.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Extruder">
+ <polygon id="Outline" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" points="52.184,51.391
+ 46.562,56.676 8.875,56.676 3.592,51.391 3.592,13.424 8.875,8.084 46.562,8.084 52.184,13.424 "/>
+
+ <circle id="Bearing" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" cx="39.736" cy="31.952" r="5.519"/>
+ <g id="Gear">
+ <path fill="#FCFAFA" d="M12.283,24.476c0.53,0.379,1.053,0.796,1.567,1.229c0.504-0.136,0.91-0.283,1.422-0.369
+ c0.243-0.04,0.583-0.021,0.718-0.096c0.239-0.137,0.399-0.614,0.546-0.861c0.188-0.315,0.336-0.587,0.495-0.874
+ c0.9-0.007,1.729,0.265,2.552,0.568c0.062,0.68,0.021,1.328,0.065,2.004c0.567,0.396,1.146,0.741,1.649,1.362
+ c0.674-0.044,1.388-0.238,2.06-0.283c0.54,0.703,0.897,1.601,1.11,2.311c-0.454,0.437-1.004,0.846-1.492,1.271
+ c0.021,0.771,0.112,1.563-0.04,2.293c0.234,0.229,0.487,0.418,0.745,0.657c0.232,0.217,0.643,0.491,0.729,0.713
+ c0.124,0.308-0.275,0.911-0.4,1.188c-0.206,0.431-0.405,0.776-0.622,1.129c-0.692-0.062-1.341-0.287-2.028-0.372
+ c-0.535,0.479-1.016,0.978-1.781,1.394c-0.141,0.692-0.065,1.441-0.226,2.128c-0.853,0.352-1.645,0.484-2.416,0.531
+ c-0.343-0.612-0.606-1.2-0.955-1.812c-0.755-0.148-1.524-0.246-2.233-0.569c-0.626,0.391-1.188,0.796-1.762,1.197
+ c-0.325-0.181-0.641-0.409-0.991-0.695c-0.276-0.225-0.814-0.554-0.915-0.879c-0.069-0.226,0.275-0.771,0.38-0.991
+ c0.174-0.379,0.318-0.653,0.434-0.978c-0.412-0.687-0.804-1.366-0.909-1.971c-0.65-0.325-1.367-0.41-2.027-0.688
+ c-0.164-0.904-0.115-1.757,0.054-2.573c0.317-0.063,0.649-0.12,0.975-0.199c0.314-0.078,0.771-0.131,0.971-0.288
+ c0.151-0.119,0.236-0.544,0.354-0.797c0.221-0.474,0.363-0.802,0.755-1.208c-0.332-0.646-0.633-1.281-0.815-1.886
+ C10.74,25.483,11.441,24.962,12.283,24.476z"/>
+ <path fill="#020000" d="M16.41,28.673c1.74,0,3.155,1.413,3.155,3.155c0,1.746-1.415,3.16-3.155,3.16
+ c-1.745,0-3.159-1.414-3.159-3.16C13.251,30.086,14.665,28.673,16.41,28.673z"/>
+ </g>
+ <g id="Filament_path">
+ <rect id="Path" x="25.212" y="8.084" fill="#FFFDFD" width="6.874" height="48.591"/>
+ <rect id="Entry" x="21.134" y="3.477" display="none" fill="#FCFCFC" width="15.032" height="4.605"/>
+ <rect id="Exit" x="21.134" y="56.676" display="none" fill="#FCFCFC" width="15.032" height="4.607"/>
+ </g>
+</g>
+<g id="Circle">
+ <g id="circle_index" transform="translate(62.000000, 173.000000)">
+ <circle id="Oval_1_" fill="#FFFFFF" cx="-15.458" cy="-159.406" r="13.594"/>
+ <text transform="matrix(1 0 0 1 -20.2341 -153.5803)" fill="#010101" font-family="'ArialMT'" font-size="16.8307">4</text>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/extruder-typeB.svg b/styles/z-bolt/images/extruder-typeB.svg
new file mode 100644
index 0000000..f6a8662
--- /dev/null
+++ b/styles/z-bolt/images/extruder-typeB.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Extruder">
+ <polygon id="Outline" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" points="52.184,51.391
+ 46.562,56.676 8.875,56.676 3.592,51.391 3.592,13.424 8.875,8.084 46.562,8.084 52.184,13.424 "/>
+
+ <circle id="Bearing" fill="none" stroke="#FCFAFA" stroke-width="3.0024" stroke-miterlimit="10" cx="39.736" cy="31.952" r="5.519"/>
+ <g id="Gear">
+ <path fill="#FCFAFA" d="M12.283,24.476c0.53,0.379,1.053,0.796,1.567,1.229c0.504-0.136,0.91-0.283,1.422-0.369
+ c0.243-0.04,0.583-0.021,0.718-0.096c0.239-0.137,0.399-0.614,0.546-0.861c0.188-0.315,0.336-0.587,0.495-0.874
+ c0.9-0.007,1.729,0.265,2.552,0.568c0.062,0.68,0.021,1.328,0.065,2.004c0.567,0.396,1.146,0.741,1.649,1.362
+ c0.674-0.044,1.388-0.238,2.06-0.283c0.54,0.703,0.897,1.601,1.11,2.311c-0.454,0.437-1.004,0.846-1.492,1.271
+ c0.021,0.771,0.112,1.563-0.04,2.293c0.234,0.229,0.487,0.418,0.745,0.657c0.232,0.217,0.643,0.491,0.729,0.713
+ c0.124,0.308-0.275,0.911-0.4,1.188c-0.206,0.431-0.405,0.776-0.622,1.129c-0.692-0.062-1.341-0.287-2.028-0.372
+ c-0.535,0.479-1.016,0.978-1.781,1.394c-0.141,0.692-0.065,1.441-0.226,2.128c-0.853,0.352-1.645,0.484-2.416,0.531
+ c-0.343-0.612-0.606-1.2-0.955-1.812c-0.755-0.148-1.524-0.246-2.233-0.569c-0.626,0.391-1.188,0.796-1.762,1.197
+ c-0.325-0.181-0.641-0.409-0.991-0.695c-0.276-0.225-0.814-0.554-0.915-0.879c-0.069-0.226,0.275-0.771,0.38-0.991
+ c0.174-0.379,0.318-0.653,0.434-0.978c-0.412-0.687-0.804-1.366-0.909-1.971c-0.65-0.325-1.367-0.41-2.027-0.688
+ c-0.164-0.904-0.115-1.757,0.054-2.573c0.317-0.063,0.649-0.12,0.975-0.199c0.314-0.078,0.771-0.131,0.971-0.288
+ c0.151-0.119,0.236-0.544,0.354-0.797c0.221-0.474,0.363-0.802,0.755-1.208c-0.332-0.646-0.633-1.281-0.815-1.886
+ C10.74,25.483,11.441,24.962,12.283,24.476z"/>
+ <path fill="#020000" d="M16.41,28.673c1.74,0,3.155,1.413,3.155,3.155c0,1.746-1.415,3.16-3.155,3.16
+ c-1.745,0-3.159-1.414-3.159-3.16C13.251,30.086,14.665,28.673,16.41,28.673z"/>
+ </g>
+ <g id="Filament_path">
+ <rect id="Path" x="25.212" y="8.084" fill="#FFFDFD" width="6.874" height="48.591"/>
+ <rect id="Entry" x="21.134" y="3.477" display="none" fill="#FCFCFC" width="15.032" height="4.605"/>
+ <rect id="Exit" x="21.134" y="56.676" display="none" fill="#FCFCFC" width="15.032" height="4.607"/>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/file-gcode.svg b/styles/z-bolt/images/file-gcode.svg
new file mode 100755
index 0000000..7ab3870
--- /dev/null
+++ b/styles/z-bolt/images/file-gcode.svg
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="68px" height="68px" viewBox="0 0 68 68" enable-background="new 0 0 68 68" xml:space="preserve">
+<g id="Layer_1_1_">
+ <g id="DocumentOutline">
+ <path id="Path" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="M40.034,4.386H16.327
+ C14.664,4.386,13,5.911,13,7.575v53.514C13,62.752,14.664,64,16.327,64h35.976c1.664,0,2.981-1.248,2.981-2.911V19.586"/>
+ <path id="Path_1_" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M53.775,20.328c1.596,0,2.012-0.832,0.832-2.01L41.23,5.009C40.121,3.9,39.081,4.316,39.081,5.91v11.646
+ c0,1.594,1.456,2.773,3.119,2.773L53.775,20.328L53.775,20.328z"/>
+ </g>
+ <g id="MockContent">
+ <path id="Path_2_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M19.239,12.705h16.636"/>
+ <path id="Path_3_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,24.489h13.864"/>
+ <path id="Path_4_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M36.568,24.489h13.17"/>
+ <path id="Path_5_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,28.648H39.34"/>
+ <path id="Path_6_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M43.5,28.648h6.238"/>
+ <path id="Path_7_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,32.807h13.864"/>
+ <path id="Path_8_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M36.568,32.807h13.17"/>
+ <path id="Path_9_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,36.966H39.34"/>
+ <path id="Path_10_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M43.5,36.966h6.238"/>
+ </g>
+ <g id="_x2E_gcode" enable-background="new ">
+ <path fill="#FFFFFF" d="M17.914,52.341c0,0.222-0.084,0.411-0.252,0.57c-0.168,0.158-0.366,0.235-0.598,0.235
+ c-0.261,0-0.474-0.077-0.643-0.235c-0.168-0.159-0.251-0.349-0.251-0.57c0-0.221,0.083-0.412,0.251-0.575
+ c0.168-0.165,0.382-0.245,0.643-0.245c0.231,0,0.43,0.08,0.598,0.245C17.83,51.929,17.914,52.12,17.914,52.341z"/>
+ <path fill="#FFFFFF" d="M20.09,55.928c-0.126-0.124-0.199-0.26-0.224-0.403c-0.023-0.144-0.004-0.269,0.058-0.374
+ c0.062-0.106,0.161-0.185,0.296-0.238c0.135-0.053,0.292-0.049,0.475,0.007c0.126,0.068,0.231,0.128,0.317,0.182
+ c0.086,0.052,0.173,0.102,0.261,0.145c0.086,0.042,0.174,0.078,0.266,0.107c0.091,0.028,0.198,0.059,0.323,0.085
+ c0.173,0.039,0.36,0.059,0.562,0.059c0.202,0,0.401-0.023,0.598-0.071c0.197-0.049,0.38-0.124,0.548-0.23
+ c0.168-0.105,0.3-0.245,0.396-0.417c0.067-0.116,0.105-0.256,0.115-0.418c0.009-0.163,0.015-0.312,0.015-0.446v-0.937
+ c-0.153,0.076-0.308,0.139-0.461,0.188c-0.153,0.048-0.312,0.097-0.476,0.144c-0.23,0.048-0.462,0.08-0.692,0.095
+ c-0.23,0.014-0.462-0.003-0.691-0.051c-0.5-0.087-0.918-0.289-1.254-0.605c-0.336-0.315-0.588-0.693-0.756-1.124
+ c-0.168-0.432-0.255-0.893-0.259-1.383c-0.005-0.49,0.073-0.951,0.238-1.384c0.134-0.346,0.331-0.662,0.59-0.951
+ c0.261-0.287,0.553-0.514,0.879-0.684c0.327-0.167,0.678-0.267,1.053-0.296c0.375-0.03,0.739,0.039,1.095,0.202
+ c0.278,0.133,0.543,0.283,0.792,0.446c0.058-0.134,0.14-0.232,0.245-0.295s0.216-0.087,0.331-0.072
+ c0.115,0.016,0.224,0.066,0.324,0.152c0.102,0.086,0.176,0.212,0.224,0.373v6.139c0,0.519-0.077,0.964-0.231,1.334
+ c-0.152,0.368-0.452,0.697-0.893,0.985c-0.183,0.115-0.379,0.217-0.591,0.304c-0.212,0.086-0.424,0.139-0.634,0.157
+ c-0.461,0.059-0.903,0.039-1.326-0.056c-0.308-0.068-0.566-0.158-0.778-0.268S20.368,56.083,20.09,55.928z M23.994,51.636
+ c0.038-0.021,0.072-0.027,0.101-0.027v-2.596c-0.009,0-0.015-0.004-0.015-0.015c-0.191-0.182-0.41-0.354-0.655-0.518
+ c-0.245-0.165-0.503-0.284-0.771-0.36c-0.115,0.01-0.231,0.021-0.346,0.028c-0.115,0.01-0.23,0.021-0.347,0.029
+ c-0.077,0.037-0.156,0.077-0.238,0.115c-0.081,0.038-0.16,0.076-0.238,0.114c-0.48,0.492-0.743,0.99-0.785,1.501
+ c-0.044,0.508,0.075,1.07,0.353,1.686c0.049,0.058,0.101,0.115,0.159,0.172c0.058,0.059,0.11,0.115,0.159,0.173
+ C22.294,52.399,23.168,52.298,23.994,51.636z"/>
+ <path fill="#FFFFFF" d="M30.362,51.534c0.164-0.134,0.324-0.196,0.483-0.187c0.159,0.009,0.286,0.062,0.382,0.159
+ c0.096,0.095,0.148,0.223,0.159,0.381c0.01,0.158-0.054,0.319-0.188,0.484c-0.316,0.344-0.689,0.591-1.117,0.734
+ s-0.85,0.185-1.269,0.121c-0.417-0.062-0.805-0.227-1.16-0.497c-0.355-0.269-0.62-0.635-0.792-1.095
+ c-0.106-0.261-0.184-0.533-0.23-0.821c-0.049-0.289-0.063-0.571-0.044-0.851c0.029-0.46,0.137-0.924,0.324-1.39
+ c0.188-0.465,0.441-0.872,0.764-1.218s0.7-0.6,1.139-0.757c0.438-0.159,0.914-0.157,1.434,0.008
+ c0.261,0.087,0.495,0.192,0.707,0.315c0.211,0.125,0.412,0.283,0.604,0.477c0.105,0.153,0.159,0.303,0.159,0.446
+ c0,0.145-0.042,0.264-0.123,0.354c-0.081,0.092-0.191,0.152-0.33,0.181c-0.14,0.027-0.296,0-0.469-0.087
+ c-0.315-0.316-0.624-0.505-0.922-0.568s-0.574-0.036-0.829,0.079c-0.255,0.114-0.479,0.3-0.678,0.553
+ c-0.196,0.256-0.349,0.544-0.454,0.864c-0.105,0.323-0.159,0.658-0.159,1.009c0,0.353,0.067,0.676,0.201,0.974
+ c0.115,0.269,0.272,0.476,0.469,0.62c0.196,0.144,0.406,0.228,0.627,0.252c0.221,0.025,0.449-0.01,0.684-0.101
+ S30.18,51.736,30.362,51.534z"/>
+ <path fill="#FFFFFF" d="M32.408,49.56c0.106-0.308,0.236-0.606,0.39-0.899c0.152-0.293,0.335-0.559,0.547-0.8
+ c0.211-0.24,0.454-0.446,0.728-0.619c0.273-0.172,0.579-0.298,0.916-0.374c0.557-0.124,1.044-0.081,1.462,0.129
+ c0.417,0.21,0.75,0.515,1.002,0.907c0.249,0.395,0.414,0.844,0.496,1.348c0.081,0.506,0.061,0.987-0.065,1.447
+ c-0.144,0.567-0.398,1.097-0.764,1.586c-0.363,0.491-0.827,0.845-1.384,1.067c-0.412,0.163-0.809,0.222-1.188,0.18
+ c-0.38-0.043-0.72-0.166-1.023-0.367c-0.303-0.201-0.561-0.467-0.771-0.792c-0.212-0.326-0.355-0.696-0.433-1.109
+ c-0.049-0.26-0.064-0.515-0.05-0.764c0.014-0.251,0.046-0.5,0.094-0.748L32.408,49.56z M33.532,49.893
+ c-0.039,0.201-0.066,0.386-0.079,0.554c-0.016,0.167-0.007,0.358,0.021,0.569c0.028,0.258,0.11,0.491,0.245,0.698
+ s0.298,0.364,0.49,0.474c0.191,0.112,0.405,0.165,0.641,0.16c0.236-0.005,0.473-0.079,0.714-0.224
+ c0.315-0.192,0.569-0.441,0.755-0.749c0.187-0.307,0.331-0.638,0.425-0.993c0.076-0.288,0.095-0.595,0.052-0.923
+ c-0.043-0.326-0.142-0.613-0.297-0.865c-0.152-0.249-0.359-0.429-0.619-0.54c-0.26-0.109-0.566-0.093-0.921,0.051
+ c-0.385,0.164-0.688,0.409-0.909,0.734C33.83,49.167,33.657,49.518,33.532,49.893z"/>
+ <path fill="#FFFFFF" d="M44.727,52.067c0.126,0.172,0.176,0.34,0.153,0.498c-0.023,0.159-0.088,0.283-0.188,0.374
+ c-0.102,0.092-0.229,0.135-0.389,0.13c-0.16-0.004-0.313-0.084-0.468-0.238c-0.049-0.048-0.092-0.099-0.129-0.151
+ c-0.039-0.054-0.068-0.104-0.088-0.15c-0.287,0.249-0.622,0.443-1,0.583c-0.38,0.138-0.764,0.209-1.153,0.209
+ c-0.389,0-0.761-0.078-1.116-0.237c-0.356-0.159-0.654-0.406-0.895-0.743c-0.181-0.259-0.313-0.551-0.396-0.872
+ s-0.122-0.647-0.122-0.98c0-0.332,0.04-0.656,0.122-0.98c0.08-0.32,0.185-0.622,0.312-0.899c0.114-0.25,0.28-0.475,0.496-0.677
+ s0.445-0.365,0.686-0.49c0.22-0.124,0.467-0.229,0.741-0.311c0.276-0.083,0.536-0.127,0.787-0.137c0.23,0,0.459,0.005,0.692,0.015
+ c0.229,0.011,0.455,0.049,0.677,0.116c-0.01-0.691-0.018-1.275-0.022-1.75c-0.005-0.476-0.007-0.795-0.007-0.959
+ c0.038-0.182,0.112-0.321,0.222-0.417c0.111-0.097,0.225-0.146,0.348-0.151c0.12-0.004,0.236,0.035,0.353,0.122
+ c0.115,0.086,0.203,0.22,0.26,0.404v7.535c0.02,0.029,0.04,0.056,0.064,0.079C44.687,52.013,44.708,52.04,44.727,52.067z
+ M43.46,51.031v-0.202c0-0.357,0-0.746,0-1.175c0-0.426-0.007-0.833-0.016-1.218l-0.085-0.042c-0.029-0.02-0.057-0.038-0.08-0.059
+ s-0.051-0.038-0.08-0.058c-0.287-0.086-0.591-0.124-0.907-0.115c-0.315,0.009-0.615,0.069-0.893,0.18
+ c-0.278,0.109-0.525,0.271-0.742,0.482c-0.216,0.213-0.366,0.48-0.454,0.807c-0.077,0.299-0.105,0.557-0.086,0.779
+ c0.019,0.222,0.048,0.479,0.086,0.777c0.038,0.076,0.074,0.153,0.108,0.231c0.033,0.075,0.069,0.152,0.107,0.229l0.29,0.29
+ c0.115,0.037,0.225,0.085,0.33,0.144c0.384,0.037,0.736,0.019,1.06-0.059c0.321-0.076,0.632-0.244,0.929-0.503
+ c0.011-0.02,0.03-0.047,0.065-0.079c0.035-0.034,0.071-0.071,0.109-0.109c0.037-0.037,0.072-0.073,0.107-0.107
+ c0.034-0.034,0.057-0.057,0.065-0.065L43.46,51.031z"/>
+ <path fill="#FFFFFF" d="M51.195,51.405c0.202-0.075,0.375-0.087,0.52-0.028c0.144,0.059,0.247,0.148,0.31,0.274
+ c0.064,0.123,0.072,0.263,0.029,0.416c-0.043,0.154-0.157,0.283-0.339,0.39c-0.317,0.183-0.658,0.351-1.022,0.504
+ c-0.366,0.153-0.736,0.259-1.109,0.316c-0.375,0.059-0.746,0.056-1.109-0.008c-0.366-0.062-0.717-0.21-1.054-0.439
+ c-0.403-0.278-0.71-0.655-0.922-1.13c-0.211-0.476-0.32-0.971-0.331-1.484c-0.011-0.515,0.084-1.009,0.28-1.484
+ c0.198-0.475,0.506-0.856,0.93-1.146c0.442-0.298,0.924-0.521,1.442-0.67s1.042-0.166,1.57-0.049
+ c0.259,0.056,0.494,0.179,0.704,0.366s0.382,0.404,0.512,0.646c0.129,0.245,0.2,0.504,0.209,0.779
+ c0.01,0.274-0.058,0.531-0.202,0.771c-0.163,0.27-0.398,0.499-0.705,0.685c-0.308,0.187-0.642,0.347-1.001,0.476
+ c-0.359,0.13-0.721,0.238-1.08,0.324s-0.676,0.169-0.943,0.245c-0.117,0.029-0.227,0.033-0.333,0.016
+ c0.146,0.308,0.359,0.559,0.643,0.755c0.283,0.197,0.637,0.28,1.059,0.254c0.337-0.021,0.677-0.115,1.017-0.281
+ C50.607,51.734,50.917,51.568,51.195,51.405z M48.386,48.336c-0.355,0.183-0.62,0.44-0.792,0.771s-0.259,0.68-0.259,1.044
+ c0.067-0.048,0.139-0.086,0.215-0.115c0.174-0.05,0.349-0.099,0.527-0.152c0.178-0.052,0.358-0.102,0.54-0.151
+ c0.115-0.028,0.271-0.07,0.469-0.13c0.196-0.056,0.4-0.123,0.611-0.2s0.404-0.167,0.577-0.267
+ c0.173-0.102,0.288-0.214,0.347-0.338c0.018-0.317-0.059-0.534-0.231-0.649c-0.172-0.114-0.38-0.172-0.62-0.172
+ s-0.49,0.04-0.748,0.122C48.761,48.18,48.55,48.26,48.386,48.336z"/>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/file-stl.svg b/styles/z-bolt/images/file-stl.svg
index 05319fd..3c46aef 100755
--- a/styles/z-bolt/images/file-stl.svg
+++ b/styles/z-bolt/images/file-stl.svg
@@ -3,44 +3,49 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="68px" height="68px" viewBox="0 0 68 68" enable-background="new 0 0 68 68" xml:space="preserve">
-<path id="Path" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="M40.034,4.386H16.327
- C14.664,4.386,13,5.911,13,7.575v53.514C13,62.752,14.664,64,16.327,64h35.976c1.664,0,2.981-1.248,2.981-2.911V21.023"/>
-<path id="Path_1_" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
- M53.776,20.328c1.595,0,2.011-0.832,0.832-2.01L41.23,5.009c-1.109-1.109-2.149-0.693-2.149,0.901v11.646
- c0,1.594,1.456,2.773,3.119,2.773H53.776z"/>
-<path id="Path_2_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M19.239,12.705h16.636"/>
-<path id="Path_3_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M18.545,24.489h13.864"/>
-<path id="Path_4_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M36.568,24.489h13.17"/>
-<path id="Path_5_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M18.545,28.648h20.795"/>
-<path id="Path_6_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M43.5,28.648h6.238"/>
-<path id="Path_7_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M18.545,32.807h13.864"/>
-<path id="Path_8_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M36.568,32.807h13.17"/>
-<path id="Path_9_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M18.545,36.966h20.795"/>
-<path id="Path_10_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
- M43.5,36.966h6.238"/>
-<g id="Group" transform="translate(19.238636, 41.125000)">
- <path id="Path_11_" fill="#FFFFFF" d="M0,13.934c0-0.555,0.139-0.971,0.416-1.248c0.277-0.277,0.693-0.416,1.317-0.416
- c0.555,0,0.97,0.139,1.248,0.416s0.416,0.693,0.416,1.248c0,0.554-0.139,0.9-0.485,1.247c-0.277,0.277-0.693,0.416-1.248,0.416
- s-0.971-0.139-1.317-0.416C0.139,14.903,0,14.487,0,13.934z"/>
- <path id="Path_12_" fill="#FFFFFF" d="M13.863,12.062c0,1.108-0.416,2.011-1.178,2.564c-0.763,0.624-1.941,0.901-3.535,0.901
- c-0.832,0-1.456-0.069-2.08-0.139c-0.485-0.139-0.832-0.277-1.525-0.485v-2.495c0.693,0.277,1.178,0.484,1.872,0.693
- c0.693,0.207,1.317,0.277,1.872,0.277c1.109,0,1.664-0.348,1.664-0.971c0-0.208-0.069-0.416-0.208-0.555s-0.416-0.347-0.763-0.485
- c-0.346-0.208-0.832-0.416-1.386-0.624c-0.832-0.346-1.456-0.693-1.872-0.971S6.031,9.15,5.823,8.734S5.546,7.833,5.546,7.278
- c0-0.97,0.347-1.733,1.109-2.288c0.763-0.554,1.802-0.831,3.258-0.831c1.317,0,2.634,0.277,3.881,0.901l-0.901,2.148
- c-0.555-0.208-1.04-0.416-1.525-0.555c-0.485-0.139-0.971-0.207-1.456-0.207c-0.901,0-1.317,0.207-1.317,0.692
- c0,0.277,0.139,0.485,0.416,0.693s0.901,0.485,1.872,0.901c0.832,0.346,1.525,0.693,1.872,0.971
- c0.416,0.277,0.693,0.623,0.901,1.039C13.794,11.091,13.863,11.507,13.863,12.062z"/>
- <path id="Path_13_" fill="#FFFFFF" d="M20.934,13.17c0.554,0,1.247-0.139,1.94-0.346v2.218c-0.693,0.347-1.732,0.485-2.842,0.485
- c-1.178,0-2.08-0.277-2.634-0.901c-0.555-0.624-0.832-1.524-0.832-2.703V6.238h-1.386v-0.9l1.594-0.971l0.832-2.287h1.803v2.079
- h3.465v2.079H19.41v5.685c0,0.416,0.207,0.763,0.484,0.97C20.102,13.031,20.518,13.17,20.934,13.17z"/>
+<g id="DocumentOutline">
+ <path id="Path" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="M40.034,4.386H16.327
+ C14.664,4.386,13,5.911,13,7.575v53.514C13,62.752,14.664,64,16.327,64h35.976c1.664,0,2.981-1.248,2.981-2.911V19.584"/>
+ <path id="Path_1_" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M53.775,20.328c1.596,0,2.012-0.832,0.832-2.01L41.23,5.009C40.121,3.9,39.081,4.316,39.081,5.91v11.646
+ c0,1.594,1.456,2.773,3.119,2.773L53.775,20.328L53.775,20.328z"/>
+</g>
+<g id="MockContent">
+ <path id="Path_2_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M19.239,12.705h16.636"/>
+ <path id="Path_3_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,24.489h13.864"/>
+ <path id="Path_4_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M36.568,24.489h13.17"/>
+ <path id="Path_5_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,28.648H39.34"/>
+ <path id="Path_6_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M43.5,28.648h6.238"/>
+ <path id="Path_7_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,32.807h13.864"/>
+ <path id="Path_8_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M36.568,32.807h13.17"/>
+ <path id="Path_9_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M18.545,36.966H39.34"/>
+ <path id="Path_10_" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" d="
+ M43.5,36.966h6.238"/>
+</g>
+<g id="_x2E_stl" transform="translate(19.238636, 41.125000)">
+ <path id="Path_11_" fill="#FFFFFF" d="M0,13.934c0-0.555,0.139-0.971,0.416-1.248c0.277-0.276,0.693-0.416,1.317-0.416
+ c0.555,0,0.97,0.14,1.248,0.416c0.278,0.277,0.416,0.693,0.416,1.248s-0.139,0.9-0.485,1.248c-0.277,0.276-0.693,0.416-1.248,0.416
+ c-0.555,0-0.971-0.14-1.317-0.416C0.139,14.902,0,14.486,0,13.934z"/>
+ <path id="Path_12_" fill="#FFFFFF" d="M13.863,12.062c0,1.107-0.416,2.011-1.178,2.563c-0.763,0.624-1.941,0.901-3.535,0.901
+ c-0.832,0-1.456-0.069-2.08-0.139c-0.485-0.14-0.832-0.277-1.525-0.486v-2.494c0.693,0.277,1.178,0.484,1.872,0.693
+ c0.693,0.207,1.317,0.276,1.872,0.276c1.109,0,1.664-0.349,1.664-0.971c0-0.208-0.069-0.416-0.208-0.556
+ c-0.139-0.139-0.416-0.347-0.763-0.484c-0.346-0.208-0.832-0.416-1.386-0.624C7.764,10.396,7.14,10.05,6.724,9.771
+ C6.308,9.494,6.031,9.15,5.823,8.734S5.546,7.833,5.546,7.277c0-0.969,0.347-1.732,1.109-2.287
+ c0.763-0.555,1.802-0.831,3.258-0.831c1.317,0,2.634,0.276,3.881,0.901l-0.901,2.147C12.338,7,11.853,6.792,11.368,6.652
+ c-0.485-0.139-0.971-0.207-1.456-0.207c-0.901,0-1.317,0.207-1.317,0.693c0,0.276,0.139,0.484,0.416,0.692
+ c0.277,0.208,0.901,0.485,1.872,0.901c0.832,0.346,1.525,0.692,1.872,0.971c0.416,0.277,0.693,0.623,0.901,1.039
+ C13.794,11.091,13.863,11.507,13.863,12.062z"/>
+ <path id="Path_13_" fill="#FFFFFF" d="M20.934,13.17c0.554,0,1.247-0.139,1.94-0.346v2.218c-0.693,0.347-1.732,0.485-2.843,0.485
+ c-1.178,0-2.08-0.277-2.634-0.901c-0.555-0.624-0.832-1.524-0.832-2.703V6.238H15.18v-0.9l1.594-0.971l0.832-2.287h1.803v2.079
+ h3.466v2.079H19.41v5.685c0,0.416,0.207,0.763,0.484,0.97C20.102,13.031,20.518,13.17,20.934,13.17z"/>
<polygon id="Path_14_" fill="#FFFFFF" points="27.727,15.25 24.955,15.25 24.955,0 27.727,0 "/>
</g>
</svg>
diff --git a/styles/z-bolt/images/octoprint-tentacle.svg b/styles/z-bolt/images/octoprint-tentacle.svg
new file mode 100755
index 0000000..4f4582e
--- /dev/null
+++ b/styles/z-bolt/images/octoprint-tentacle.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_2_1_">
+ <path fill="none" stroke="#FFFFFF" stroke-width="2.2536" stroke-miterlimit="10" d="M9.45,53.992c0,0-2.5-6.849-3.167-9.062
+ c-0.669-2.214-0.734-2.577-1.014-4.597c-0.278-2.018-0.259-2.985-0.259-2.985s-0.215-4.389-0.157-5.866
+ c0.06-1.481,0.688-5.511,1.065-6.621c0.376-1.11,1.752-3.667,2.622-4.959c0.87-1.291,2.389-2.954,3.322-3.895
+ c0.936-0.94,4.129-3.389,5.142-4.102c1.012-0.715,3.73-2.136,5.322-2.778c1.59-0.643,4.829-1.351,4.829-1.351l2.673-0.389
+ c0,0,2.688-0.306,5.115-0.13c2.526,0.312,3.789,0.598,3.789,0.598s2.224,0.567,3.87,1.221c1.646,0.653,1.566,0.589,3.142,1.428
+ c2.221,1.232,3.121,1.954,4.568,3.143c1.993,1.812,3.297,3.946,3.297,3.946l0.936,1.661c0,0,0.596,1.292,0.908,2.415
+ c0.312,1.122,0.312,1.122,0.442,2.519c0.131,1.396,0.077,2.908,0.077,2.908s-0.688-0.962-1.663-2.025
+ c-0.972-1.065-2.18-1.902-3.504-2.856c-1.322-0.954-3.441-1.925-3.441-1.925s-2.304-1.12-3.802-1.477
+ c-1.5-0.356-3.115-0.391-3.115-0.391l-2.855-0.077c0,0-2.162,0.11-3.597,0.52c-1.434,0.408-3.518,1.428-3.518,1.428
+ s-1.26,0.695-2.363,1.533c-1.103,0.836-1.896,1.868-1.896,1.868l-1.116,1.662c0,0-0.539,1.057-0.676,2.024s-0.137,0.968-0.13,2.233
+ s0.019,0.922,0.442,2.233c0.422,1.31,1.453,3.167,1.453,3.167l1.714,2.855l3.712,5.479l2.207,3.66l1.507,2.884
+ c0,0,0.615,1.173,1.062,2.103c0.449,0.927,0.702,1.999,0.702,1.999H9.45V53.992z"/>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/open.svg b/styles/z-bolt/images/open.svg
index 7802389..6d783b7 100644..100755
--- a/styles/z-bolt/images/open.svg
+++ b/styles/z-bolt/images/open.svg
@@ -1,11 +1,12 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
- <title>open</title>
- <desc>Created with Sketch.</desc>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
- <g id="load" transform="translate(29.000000, 30.000000) rotate(90.000000) translate(-29.000000, -30.000000) translate(10.000000, 9.000000)" fill="#232323" stroke="#FFFFFF" stroke-width="3">
- <polygon id="path7561-4-3" points="36.7466734 18.2023592 19.1610914 0.4322738 1.3910064 18.0178552 8.4256294 25.1258922 14.1191704 19.4912442 13.8826214 40.2301292 23.8819714 40.3441822 24.1179184 19.6580282 29.6386334 25.2369812"></polygon>
- </g>
- </g>
-</svg> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60px" height="60px" viewBox="0 0 60 60" enable-background="new 0 0 60 60" xml:space="preserve">
+ <g id="Page-1">
+ <g id="load" transform="translate(29.000000, 30.000000) rotate(90.000000) translate(-29.000000, -30.000000) translate(10.000000, 9.000000)">
+ <polygon id="path7561-4-3" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" points="36.746,18.202
+ 19.161,0.432 1.391,18.018 8.426,25.126 14.119,19.491 13.883,40.23 23.882,40.344 24.118,19.658 29.639,25.237 "/>
+ </g>
+ </g>
+</svg>
diff --git a/styles/z-bolt/images/sd-eject.svg b/styles/z-bolt/images/sd-eject.svg
index 755e60b..61c8d49 100644
--- a/styles/z-bolt/images/sd-eject.svg
+++ b/styles/z-bolt/images/sd-eject.svg
@@ -1,149 +1,41 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="60.13768"
- height="60.776516"
- viewBox="0 0 60.137677 60.776516"
- id="svg4160"
- version="1.1"
- inkscape:version="0.92.2 5c3e80d, 2017-08-06"
- sodipodi:docname="sd_eject.svg">
- <defs
- id="defs4162" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="10.10182"
- inkscape:cx="104.44588"
- inkscape:cy="1.8948894"
- inkscape:document-units="px"
- inkscape:current-layer="layer2"
- showgrid="true"
- units="in"
- showguides="false"
- inkscape:window-width="3200"
- inkscape:window-height="1800"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="0"
- inkscape:snap-bbox="true"
- inkscape:snap-global="false">
- <inkscape:grid
- type="xygrid"
- id="grid4712"
- originx="-9.9771178"
- originy="-29.820954" />
- </sodipodi:namedview>
- <metadata
- id="metadata4165">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="HeatBed 1" />
- <g
- inkscape:groupmode="layer"
- id="layer1"
- inkscape:label="HeatBed"
- transform="translate(-9.9771186,-13.402532)"
- style="display:inline">
- <g
- transform="matrix(0.7803205,0,0,0.7803205,9.3637737,9.3173446)"
- id="g43">
- <path
- sodipodi:nodetypes="cccccccccc"
- inkscape:connector-curvature="0"
- id="rect4373"
- d="M 27.876889,14.229697 H 39.319978 50.763066 62.206154 V 74.356291 H 16.433802 V 59.324642 44.292994 29.261346 Z"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.242296"
- x="29.107141"
- height="11"
- width="2"
- id="rect4378"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.297136"
- x="37.063133"
- height="11"
- width="2"
- id="rect4378-7"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.129396"
- x="45.464287"
- height="11"
- width="2"
- id="rect4378-8"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.103247"
- x="53.759563"
- height="11"
- width="2"
- id="rect4378-76"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </g>
- <g
- id="g48"
- transform="translate(-40.668816,10.079706)">
- <g
- id="g32"
- transform="translate(-61.276088,-5.0485953)">
- <g
- id="g38"
- transform="matrix(0,-0.70504127,0.70504127,0,129.48706,85.720049)">
- <path
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0"
- id="rect4760-8"
- d="m 22.795553,16.619161 3.21242,-1.25 3.212421,1.25 v 47.687531 l -3.212421,0.892857 -3.21242,-0.892857 z"
- style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- inkscape:connector-curvature="0"
- id="path4535"
- d="m 36.118518,28.116475 -0.0029,29.98228 -5.617131,-10e-4 0.0029,-29.98228 z"
- style="fill:none;fill-rule:evenodd;stroke:#FFFFFF;stroke-width:1.94661856;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0"
- id="path4293"
- d="M 41.862434,28.576104 56.905551,43.106805 41.817663,57.637506 V 28.576104"
- style="fill:none;fill-rule:evenodd;stroke:#FFFFFF;stroke-width:2.95693779;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </g>
- <path
- style="fill:#FFFFFF;fill-opacity:1;stroke-width:0.04908723"
- d="m 151.8202,55.343347 c 0.79813,-0.853251 8.21066,-8.503843 8.23923,-8.503843 0.036,0 8.33397,8.593793 8.44106,8.741968 0.0661,0.09143 -0.0935,0.09319 -8.46143,0.09319 h -8.52877 z"
- id="path22"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#FFFFFF;fill-opacity:1;stroke-width:0.03805283"
- d="m 149.89025,62.19596 v -2.129986 h 10.39471 10.39469 v 2.129986 2.129987 h -10.39469 -10.39471 z"
- id="path35"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- </g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+ id="layer1_1_" sodipodi:docname="sd_eject.svg" inkscape:version="0.92.2 5c3e80d, 2017-08-06" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="60.137px"
+ height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="layer2" transform="translate(-9.9771186,-13.402532)" inkscape:label="HeatBed" inkscape:groupmode="layer">
+ <g id="SD_Card" transform="matrix(0.7803205,0,0,0.7803205,9.3637737,9.3173446)">
+
+ <path id="Outline" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="
+ M27.877,14.23H39.32h11.444h11.442v60.127H16.434V59.324V44.293V29.261L27.877,14.23z"/>
+ <g id="Pins">
+
+ <rect id="rect4378" x="29.107" y="22.242" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2" height="11"/>
+
+ <rect id="rect4378-7" x="37.063" y="22.297" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2.001" height="11"/>
+
+ <rect id="rect4378-8" x="45.465" y="22.129" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2" height="11.001"/>
+
+ <rect id="rect4378-76" x="53.76" y="22.103" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2" height="11"/>
+ </g>
+ </g>
+ <g id="Eject_Symbol" transform="translate(-40.668816,10.079706)">
+ <g id="g38" transform="matrix(0,-0.70504127,0.70504127,0,129.48706,85.720049)">
+ <path id="rect4760-8" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccc" fill="none" d="M29.956-70.292l3.213-1.25
+ l3.211,1.25v47.687l-3.211,0.893l-3.213-0.893V-70.292z"/>
+
+ <path id="path4535" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="1.9466" stroke-linejoin="round" d="
+ M43.278-58.795l-0.003,29.982l-5.615-0.001l0.003-29.982L43.278-58.795z"/>
+
+ <path id="path4293" inkscape:connector-curvature="0" sodipodi:nodetypes="cccc" fill="none" stroke="#FFFFFF" stroke-width="2.9569" stroke-linecap="round" stroke-linejoin="round" d="
+ M49.024-58.335l15.042,14.531l-15.087,14.53v-29.061"/>
+ </g>
+ <path id="path22" inkscape:connector-curvature="0" fill="#FFFFFF" d="M90.544,50.295c0.798-0.854,8.211-8.504,8.239-8.504
+ c0.036,0,8.334,8.594,8.441,8.742c0.066,0.092-0.094,0.093-8.461,0.093h-8.529L90.544,50.295z"/>
+ <path id="path35" inkscape:connector-curvature="0" fill="#FFFFFF" d="M88.614,57.148v-2.13h10.395h10.396v2.13v2.13H99.009
+ H88.614V57.148z"/>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/sd.svg b/styles/z-bolt/images/sd.svg
index 356e5c1..16e2b88 100644..100755
--- a/styles/z-bolt/images/sd.svg
+++ b/styles/z-bolt/images/sd.svg
@@ -1,110 +1,25 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="60.13768"
- height="60.776516"
- viewBox="0 0 60.137677 60.776516"
- id="svg4160"
- version="1.1"
- inkscape:version="0.92.2 5c3e80d, 2017-08-06"
- sodipodi:docname="sd.svg">
- <defs
- id="defs4162" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="11.2"
- inkscape:cx="41.378767"
- inkscape:cy="37.332473"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="true"
- units="in"
- showguides="false"
- inkscape:window-width="3200"
- inkscape:window-height="1800"
- inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="0"
- inkscape:snap-bbox="true"
- inkscape:snap-global="false">
- <inkscape:grid
- type="xygrid"
- id="grid4712"
- originx="-9.9771178"
- originy="-29.820954" />
- </sodipodi:namedview>
- <metadata
- id="metadata4165">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="HeatBed 1" />
- <g
- inkscape:groupmode="layer"
- id="layer1"
- inkscape:label="HeatBed"
- transform="translate(-9.9771186,-13.402532)"
- style="display:inline">
- <g
- transform="matrix(0.7803205,0,0,0.7803205,9.3637737,9.3173446)"
- id="g43">
- <path
- sodipodi:nodetypes="cccccccccc"
- inkscape:connector-curvature="0"
- id="rect4373"
- d="M 27.876889,14.229697 H 39.319978 50.763066 62.206154 V 74.356291 H 16.433802 V 59.324642 44.292994 29.261346 Z"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.242296"
- x="29.107141"
- height="11"
- width="2"
- id="rect4378"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.297136"
- x="37.063133"
- height="11"
- width="2"
- id="rect4378-7"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.129396"
- x="45.464287"
- height="11"
- width="2"
- id="rect4378-8"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="22.103247"
- x="53.759563"
- height="11"
- width="2"
- id="rect4378-76"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </g>
- </g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+ id="layer1_1_" sodipodi:docname="sd_eject.svg" inkscape:version="0.92.2 5c3e80d, 2017-08-06" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="60.137px"
+ height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="layer2" transform="translate(-9.9771186,-13.402532)" inkscape:groupmode="layer" inkscape:label="HeatBed">
+ <g id="SD_Card" transform="matrix(0.7803205,0,0,0.7803205,9.3637737,9.3173446)">
+
+ <path id="Outline" sodipodi:nodetypes="cccccccccc" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="
+ M27.877,14.229H39.32h11.445h11.441v60.128H16.434V59.324V44.293V29.261L27.877,14.229z"/>
+ <g id="Pins">
+
+ <rect id="rect4378" x="29.108" y="22.241" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2" height="11.001"/>
+
+ <rect id="rect4378-7" x="37.063" y="22.297" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2.001" height="11.001"/>
+
+ <rect id="rect4378-8" x="45.464" y="22.129" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2.001" height="11.001"/>
+
+ <rect id="rect4378-76" x="53.761" y="22.103" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" width="2" height="11.001"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-0%.svg b/styles/z-bolt/images/speed-0%.svg
new file mode 100644
index 0000000..05a2426
--- /dev/null
+++ b/styles/z-bolt/images/speed-0%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-0_x25_">
+
+ <path id="cone_1_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M17.75,46.857l9.192-12.021l2.828,2.827L17.75,46.857z"/>
+
+ <circle id="dot_1_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.206" cy="34.35" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-100%.svg b/styles/z-bolt/images/speed-100%.svg
new file mode 100644
index 0000000..b50ef03
--- /dev/null
+++ b/styles/z-bolt/images/speed-100%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-100_x25_">
+
+ <path id="cone_2_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M42.714,46.805l-12.021-9.193l2.827-2.828L42.714,46.805z"/>
+
+ <circle id="dot_2_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.207" cy="34.349" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-17%.svg b/styles/z-bolt/images/speed-17%.svg
new file mode 100644
index 0000000..b2cddc5
--- /dev/null
+++ b/styles/z-bolt/images/speed-17%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-17_x25_">
+
+ <path id="cone_3_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M12.555,34.385l15-1.999l0.001,3.999L12.555,34.385z"/>
+
+ <circle id="dot_3_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.207" cy="34.349" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-34%.svg b/styles/z-bolt/images/speed-34%.svg
new file mode 100644
index 0000000..69c3f69
--- /dev/null
+++ b/styles/z-bolt/images/speed-34%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-34_x25_">
+
+ <path id="cone_4_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M17.7,21.893l12.021,9.192l-2.827,2.828L17.7,21.893z"/>
+
+ <circle id="dot_4_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.207" cy="34.349" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-50%.svg b/styles/z-bolt/images/speed-50%.svg
new file mode 100644
index 0000000..839edb1
--- /dev/null
+++ b/styles/z-bolt/images/speed-50%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-50_x25_">
+
+ <path id="cone_5_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.17,16.697l2,15.002h-3.999L30.17,16.697z"/>
+
+ <circle id="dot_5_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.207" cy="34.349" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-67%.svg b/styles/z-bolt/images/speed-67%.svg
new file mode 100644
index 0000000..1ab657c
--- /dev/null
+++ b/styles/z-bolt/images/speed-67%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-67_x25_">
+
+ <path id="cone_6_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M42.663,21.843L33.47,33.866l-2.828-2.828L42.663,21.843z"/>
+
+ <circle id="dot_6_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.208" cy="34.35" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/speed-83%.svg b/styles/z-bolt/images/speed-83%.svg
new file mode 100644
index 0000000..b191401
--- /dev/null
+++ b/styles/z-bolt/images/speed-83%.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="60.137px" height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<g id="Layer_1_2_">
+ <g id="Layer_1_1_">
+
+ <g id="group" inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="speed-step.svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+
+ <path id="arch" inkscape:connector-curvature="0" sodipodi:nodetypes="csssc" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M11.583,53C6.82,48.218,3.872,41.617,3.872,34.322c0-14.587,11.786-26.413,26.322-26.413c14.534,0,26.32,11.826,26.32,26.413
+ c0,7.295-2.94,13.901-7.71,18.678"/>
+
+ <path id="_x31_00_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M45.069,49.31l3.685,3.652"/>
+
+ <path id="_x38_3_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M50.662,34.322h4.998"/>
+
+ <path id="_x36_7_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M44.867,19.688l3.544-3.534"/>
+
+ <path id="_x35_0_x25_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M30.195,13.34v-5"/>
+
+ <path id="_x33_4_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.368,19.745l-3.482-3.424"/>
+
+ <path id="_x31_7_x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M9.569,34.322h-5"/>
+
+ <path id="_x30__x25__1_" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="
+ M15.069,49.513l-3.502,3.542"/>
+ <g id="needle-83_x25_">
+
+ <path id="cone_7_" inkscape:connector-curvature="0" fill="#FFFFFF" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" d="
+ M47.859,34.312l-15.003,2.001l0.001-3.999L47.859,34.312z"/>
+
+ <circle id="dot_7_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="30.207" cy="34.349" r="2.5"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/z-calibration.svg b/styles/z-bolt/images/z-calibration.svg
index a30ef8d..a2e7642 100644
--- a/styles/z-bolt/images/z-calibration.svg
+++ b/styles/z-bolt/images/z-calibration.svg
@@ -1,97 +1,23 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="60.13768"
- height="60.776516"
- viewBox="0 0 60.137677 60.776516"
- id="svg4160"
- version="1.1"
- inkscape:version="0.92.2 5c3e80d, 2017-08-06"
- sodipodi:docname="home-z.svg">
- <defs
- id="defs4162" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="5.6"
- inkscape:cx="-133.6799"
- inkscape:cy="7.2709709"
- inkscape:document-units="px"
- inkscape:current-layer="layer3"
- showgrid="true"
- units="in"
- showguides="false"
- inkscape:window-width="3196"
- inkscape:window-height="878"
- inkscape:window-x="0"
- inkscape:window-y="882"
- inkscape:window-maximized="0"
- inkscape:snap-bbox="true"
- inkscape:snap-global="false">
- <inkscape:grid
- type="xygrid"
- id="grid4712"
- originx="-9.9771178"
- originy="-29.820954" />
- </sodipodi:namedview>
- <metadata
- id="metadata4165">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:groupmode="layer"
- id="layer3"
- inkscape:label="Home"
- style="display:inline"
- transform="translate(-3.5328446,2.2636422)">
- <g
- transform="translate(-6.3983144,-14.354528)"
- id="g39">
- <path
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0"
- id="rect4760-8"
- d="m 22.795553,16.619161 3.21242,-1.25 3.212421,1.25 v 47.687531 l -3.212421,0.892857 -3.21242,-0.892857 z"
- style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- y="64.121429"
- x="14.050002"
- height="5.8285666"
- width="51.899994"
- id="rect7837"
- style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- inkscape:connector-curvature="0"
- id="path7561-4"
- d="M 56.941331,35.239568 39.355752,53.009653 21.585667,35.424072 l 7.034623,-7.108037 5.693541,5.634648 -0.236549,-20.738885 9.99935,-0.114053 0.235947,20.686154 5.520713,-5.578953 z"
- style="fill:#232323;fill-opacity:1;fill-rule:evenodd;stroke:#FFFFFF;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <circle
- transform="rotate(-89.382484)"
- r="5"
- cy="40.673439"
- cx="-66.426041"
- id="path8128"
- style="fill:#FFFFFF;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </g>
- </g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+ id="svg4160" xmlns:dc="http://purl.org/dc/elements/1.1/" sodipodi:docname="home-z.svg" inkscape:version="0.92.2 5c3e80d, 2017-08-06" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:cc="http://creativecommons.org/ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="60.137px"
+ height="60.777px" viewBox="0 0 60.137 60.777" enable-background="new 0 0 60.137 60.777" xml:space="preserve">
+<sodipodi:namedview units="in" pagecolor="#ffffff" bordercolor="#666666" inkscape:window-maximized="0" inkscape:snap-bbox="true" inkscape:snap-global="false" inkscape:window-height="878" inkscape:pageshadow="2" inkscape:zoom="5.6" inkscape:cx="-133.6799" inkscape:cy="7.2709709" inkscape:document-units="px" showgrid="true" showguides="false" inkscape:window-width="3196" inkscape:window-x="0" inkscape:window-y="882" inkscape:current-layer="layer3" borderopacity="1.0" id="base" inkscape:pageopacity="0.0">
+ <inkscape:grid type="xygrid" originx="-9.9771178" originy="-29.820954" id="grid4712"></inkscape:grid>
+</sodipodi:namedview>
+<g id="layer3" transform="translate(-3.5328446,2.2636422)" inkscape:groupmode="layer" inkscape:label="Home">
+ <g id="g39" transform="translate(-6.3983144,-14.354528)">
+
+ <rect id="rect7837" x="14.05" y="64.122" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" width="51.9" height="5.828"/>
+
+ <path id="path7561-4" inkscape:connector-curvature="0" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" d="
+ M56.941,35.239L39.356,53.01L21.585,35.424l7.035-7.108l5.694,5.635l-0.237-20.739l9.999-0.114l0.236,20.686l5.521-5.579
+ L56.941,35.239z"/>
+
+ <circle id="path8128" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" cx="39.955" cy="66.861" r="5"/>
+ </g>
+</g>
+</svg>
diff --git a/styles/z-bolt/images/z-offset-decrease.svg b/styles/z-bolt/images/z-offset-decrease.svg
index 6ec00dd..c0bd6db 100644
--- a/styles/z-bolt/images/z-offset-decrease.svg
+++ b/styles/z-bolt/images/z-offset-decrease.svg
@@ -47,6 +47,6 @@
<line fill="none" stroke="#FFFFFF" stroke-width="1.7437" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="20.862" y1="24.402" x2="16.616" y2="24.402"/>
</g>
</g>
-<path id="Arrow_1_" fill="#232323" stroke="#FFFFFF" stroke-width="2.4221" stroke-linejoin="round" d="M65.188,20.783
- L50.991,35.131L36.645,20.932l5.679-5.738l4.598,4.549V3h8.073l-0.001,16.609l4.458-4.504L65.188,20.783z"/>
+<path id="Arrow_1_" fill="none" stroke="#FFFFFF" stroke-width="2.4221" stroke-linejoin="round" d="M65.188,20.783L50.991,35.131
+ L36.645,20.932l5.68-5.738l4.598,4.549V3h8.073l-0.001,16.609l4.458-4.504L65.188,20.783z"/>
</svg>
diff --git a/styles/z-bolt/images/z-offset-increase.svg b/styles/z-bolt/images/z-offset-increase.svg
index f0a836d..4a99b1f 100644
--- a/styles/z-bolt/images/z-offset-increase.svg
+++ b/styles/z-bolt/images/z-offset-increase.svg
@@ -12,7 +12,7 @@
<path id="Path_5_" fill="none" stroke="#FFFFFF" stroke-linecap="round" d="M48.02,52.412l3.295-7.688"/>
<path id="Path_6_" fill="none" stroke="#FFFFFF" stroke-linecap="round" d="M55.706,52.412L59,44.727"/>
<path id="Path_7_" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M66.688,47.953
- c0-1.768-1.439-3.229-3.186-3.229H6.185C4.44,44.727,3,46.186,3,47.953v1.23c0,1.768,1.44,3.229,3.185,3.229h57.317
+ c0-1.768-1.438-3.229-3.186-3.229H6.185C4.44,44.727,3,46.186,3,47.953v1.23c0,1.768,1.44,3.229,3.185,3.229h57.317
c1.744,0,3.186-1.461,3.186-3.229V47.953L66.688,47.953z"/>
<polyline id="Path_8_" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" points="8.49,54.607 8.49,59
15.079,59 15.079,54.607 "/>
@@ -47,6 +47,6 @@
<line fill="none" stroke="#FFFFFF" stroke-width="1.7437" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="20.862" y1="24.402" x2="16.616" y2="24.402"/>
</g>
</g>
-<path id="Arrow_1_" fill="#232323" stroke="#FFFFFF" stroke-width="2.4221" stroke-linejoin="round" d="M59.451,23.026l-4.458-4.504
+<path id="Arrow_1_" fill="none" stroke="#FFFFFF" stroke-width="2.4221" stroke-linejoin="round" d="M59.451,23.026l-4.458-4.504
l0.001,16.609h-8.073V18.388l-4.598,4.549l-5.679-5.738L50.991,3l14.196,14.348L59.451,23.026z"/>
</svg>
diff --git a/styles/z-bolt/style.css b/styles/z-bolt/style.css
index 461b055..be4fa94 100755
--- a/styles/z-bolt/style.css
+++ b/styles/z-bolt/style.css
@@ -36,6 +36,33 @@ progress {
}
+/* File browser *********************************************************** */
+.list-item-nth-child-even {
+ background-color: #34383C;
+}
+
+.labels-box {
+ margin-top: 10px;
+}
+
+.preview-image-list-item {
+ margin-bottom: 15px;
+}
+
+
+.list-box-row {
+ margin: 0;
+ border: 0;
+ padding: 0;
+}
+
+.list-item-button {
+ margin: 0;
+ border: 0;
+ padding: 0 0 0 6px;
+}
+
+
/* Button styles *********************************************************** */
@@ -58,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;
@@ -82,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;
@@ -90,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;
}
@@ -105,9 +132,7 @@ button.active {
background-color: #20303D;
}
-button.file-list {
- margin: 0px;
-}
+
entry {
font-size: 30px;
@@ -120,12 +145,13 @@ entry {
button.keyboard {
font-size: 30px;
- margin: 0px;
- /* margin-bottom: 10px; */
+ margin: 2px;
+ background-color: #538fbe;
+ border: 5px outset #2d6898;
}
.dialog {
- border: 2px solid black;
+ border: 4px solid white;
font-size: 20px;
padding: 50px;
background-color: #333;
@@ -335,6 +361,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/BedLevelPanel.go b/ui/BedLevelPanel.go
index bf1189f..b96290f 100755
--- a/ui/BedLevelPanel.go
+++ b/ui/BedLevelPanel.go
@@ -4,8 +4,10 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
"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"
)
@@ -104,23 +106,21 @@ func (this *bedLevelPanel) addBedLevelCornerButton(isLeft, isTop bool) {
}
func (this *bedLevelPanel) defineLevelingPoints() {
- utils.Logger.Debug("entering BedLevelPanel.verifyConnection()")
+ logger.TraceEnter("BedLevelPanel.defineLevelingPoints()")
- connectionRequest, err := (&octoprint.ConnectionRequest{}).Do(this.UI.Client)
+ connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.UI.Client)
if err != nil {
- utils.LogError("BedLevelPanel.defineLevelingPoints()", "Do(ConnectionRequest)", err)
-
- utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()")
+ logger.LogError("BedLevelPanel.defineLevelingPoints()", "version.Get()", err)
+ logger.TraceLeave("BedLevelPanel.defineLevelingPoints()")
return
}
- utils.Logger.Info(connectionRequest.Current.PrinterProfile)
+ logger.Info(connectionResponse.Current.PrinterProfile)
- printerProfile, err := (&octoprint.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)
-
- utils.Logger.Debug("leaving BedLevelPanel.verifyConnection()")
+ logger.LogError("BedLevelPanel.defineLevelingPoints()", "Do(PrinterProfilesRequest)", err)
+ logger.TraceLeave("BedLevelPanel.defineLevelingPoints()")
return
}
@@ -136,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 {
@@ -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]),
@@ -153,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
}
})
@@ -166,13 +166,13 @@ func (this *bedLevelPanel) goHomeIfRequired() {
return
}
- cmd := &octoprint.CommandRequest{}
+ cmd := &octoprintApis.CommandRequest{}
cmd.Commands = []string{
"G28",
}
if err := cmd.Do(this.UI.Client); err != nil {
- utils.LogError("BedLevelPanel.goHomeIfRequire()", "Do(CommandRequest)", err)
+ logger.LogError("BedLevelPanel.goHomeIfRequire()", "Do(CommandRequest)", err)
return
}
@@ -181,13 +181,13 @@ 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,
}
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/CommonPanel.go b/ui/CommonPanel.go
index c030c33..0dd2a12 100755
--- a/ui/CommonPanel.go
+++ b/ui/CommonPanel.go
@@ -9,13 +9,14 @@ 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/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 []octoprint.MenuItem,
+ items []dataModels.MenuItem,
cols int,
) {
for i, item := range items {
@@ -123,7 +124,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/ConnectionPanel.go b/ui/ConnectionPanel.go
index 34b9182..5ec3d43 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 {
diff --git a/ui/ControlPanel.go b/ui/ControlPanel.go
index 7f981b9..71fc839 100755
--- a/ui/ControlPanel.go
+++ b/ui/ControlPanel.go
@@ -4,10 +4,12 @@ import (
"strings"
// "github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
"github.com/Z-Bolt/OctoScreen/interfaces"
+ "github.com/Z-Bolt/OctoScreen/logger"
"github.com/Z-Bolt/OctoScreen/uiWidgets"
- "github.com/Z-Bolt/OctoScreen/utils"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+ // "github.com/Z-Bolt/OctoScreen/utils"
)
var controlPanelInstance *controlPanel
@@ -51,8 +53,8 @@ func (this *controlPanel) initialize() {
}
}
-func (this *controlPanel) getDefaultControls() []*octoprint.ControlDefinition {
- var controlDefinitions = []*octoprint.ControlDefinition{{
+func (this *controlPanel) getDefaultControls() []*dataModels.ControlDefinition {
+ var controlDefinitions = []*dataModels.ControlDefinition{{
Name: "Motor Off",
Command: "M18", // Disable all stepper motors immediately
}, {
@@ -69,19 +71,19 @@ func (this *controlPanel) getDefaultControls() []*octoprint.ControlDefinition {
return controlDefinitions
}
-func (this *controlPanel) getCustomControls() []*octoprint.ControlDefinition {
- controlDefinitions := []*octoprint.ControlDefinition{}
+func (this *controlPanel) getCustomControls() []*dataModels.ControlDefinition {
+ controlDefinitions := []*dataModels.ControlDefinition{}
- utils.Logger.Info("control.getCustomControl() - Retrieving custom controls")
- response, err := (&octoprint.CustomCommandsRequest{}).Do(this.UI.Client)
+ 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
}
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)
}
}
@@ -90,11 +92,11 @@ func (this *controlPanel) getCustomControls() []*octoprint.ControlDefinition {
return controlDefinitions
}
-func (this *controlPanel) getCommands() []*octoprint.CommandDefinition {
- utils.Logger.Info("Retrieving custom commands")
- response, err := (&octoprint.SystemCommandsRequest{}).Do(this.UI.Client)
+func (this *controlPanel) getCommands() []*dataModels.CommandDefinition {
+ 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/CustomItemsPanel.go b/ui/CustomItemsPanel.go
index a3101f3..fb39399 100755
--- a/ui/CustomItemsPanel.go
+++ b/ui/CustomItemsPanel.go
@@ -1,20 +1,21 @@
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/octoprintApis/dataModels"
// "github.com/Z-Bolt/OctoScreen/uiWidgets"
)
type customItemsPanel struct {
CommonPanel
- items []octoprint.MenuItem
+ items []dataModels.MenuItem
}
func CustomItemsPanel(
ui *UI,
parentPanel interfaces.IPanel,
- items []octoprint.MenuItem,
+ items []dataModels.MenuItem,
) *customItemsPanel {
instance := &customItemsPanel {
CommonPanel: NewCommonPanel(ui, parentPanel),
diff --git a/ui/FanPanel.go b/ui/FanPanel.go
index 91087dd..ea02e5c 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/FatalErrorWindow.go b/ui/FatalErrorWindow.go
index ce38776..5fbea62 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/FilamentPanel.go b/ui/FilamentPanel.go
index 68d494b..df7e313 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"
@@ -30,7 +29,7 @@ type filamentPanel struct {
// Third row
temperatureButton *gtk.Button
- selectToolStepButton *uiWidgets.SelectToolStepButton
+ selectExtruderStepButton *uiWidgets.SelectToolStepButton
}
func FilamentPanel(
@@ -54,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
@@ -63,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)
@@ -77,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,8 +86,10 @@ func (this *filamentPanel) initialize() {
this.filamentLoadButton = uiWidgets.CreateFilamentLoadButton(
this.UI.window,
this.UI.Client,
- this.selectToolStepButton,
+ this.flowRateStepButton,
+ this.selectExtruderStepButton,
true,
+ int(this.UI.Settings.FilamentInLength),
)
this.Grid().Attach(this.filamentLoadButton, 0, 1, 1, 1)
@@ -98,8 +99,10 @@ func (this *filamentPanel) initialize() {
this.filamentUnloadButton = uiWidgets.CreateFilamentLoadButton(
this.UI.window,
this.UI.Client,
- this.selectToolStepButton,
+ this.flowRateStepButton,
+ this.selectExtruderStepButton,
false,
+ int(this.UI.Settings.FilamentOutLength),
)
this.Grid().Attach(this.filamentUnloadButton, 3, 1, 1, 1)
@@ -109,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/FilesPanel.go b/ui/FilesPanel.go
index 19140a3..3d749f0 100755
--- a/ui/FilesPanel.go
+++ b/ui/FilesPanel.go
@@ -2,23 +2,32 @@ package ui
import (
"fmt"
+ "os"
"sort"
+ "strings"
+ "time"
+ "github.com/coreos/go-systemd/daemon"
"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/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"
)
+
var filesPanelInstance *filesPanel
type filesPanel struct {
CommonPanel
listBox *gtk.Box
- locationHistory locationHistory
+ refreshButton *gtk.Button
+ backButton *gtk.Button
+ locationHistory utils.LocationHistory
}
func FilesPanel(
@@ -26,8 +35,8 @@ func FilesPanel(
parentPanel interfaces.IPanel,
) *filesPanel {
if filesPanelInstance == nil {
- locationHistory := locationHistory {
- locations: []octoprint.Location{octoprint.Local},
+ locationHistory := utils.LocationHistory {
+ Locations: []dataModels.Location{},
}
instance := &filesPanel {
@@ -51,13 +60,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.Box {
actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
actionBar.SetHAlign(gtk.ALIGN_END)
actionBar.SetHExpand(true)
@@ -65,187 +74,491 @@ func (this *filesPanel) createActionBar() 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, this.goBack)
+}
- // TODO: look into making a BackButton class
+func (this *filesPanel) doLoadFiles() {
+
+ this.UI.sdNotify(daemon.SdNotifyWatchdog)
+
+ 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.
+ */
+ if atRootLevel && !this.sdIsReady() {
+ atRootLevel = false
+ this.locationHistory = utils.LocationHistory {
+ Locations: []dataModels.Location{dataModels.Local},
+ }
+ }
+ if atRootLevel {
+ this.addRootLocations()
+ } else {
+ sortedFiles := this.getSortedFiles()
+ this.addSortedFiles(sortedFiles)
+ }
+ this.listBox.ShowAll()
+}
- image := utils.MustImageFromFileWithSize("back.svg", this.Scaled(40), this.Scaled(40))
- return utils.MustButton(image, func() {
- if this.locationHistory.isRoot() {
- this.UI.GoToPreviousPanel()
+func (this *filesPanel) sdIsReady() bool {
+ err := (&octoprintApis.SdRefreshRequest {}).Do(this.UI.Client)
+ if err == nil {
+ sdState, err := (&octoprintApis.SdStateRequest {}).Do(this.UI.Client)
+ if err == nil && sdState.IsReady == true {
+ return true
} else {
- this.locationHistory.goBack()
+ return false
+ }
+ } else {
+ return false
+ }
+}
+
+func (this *filesPanel) goBack() {
+ if this.displayRootLocations() {
+ this.UI.GoToPreviousPanel()
+ } else if this.locationHistory.IsRoot() {
+ this.locationHistory.GoBack()
+ if this.sdIsReady() {
this.doLoadFiles()
+ } else {
+ this.UI.GoToPreviousPanel()
}
- })
+ } else {
+ this.locationHistory.GoBack()
+ this.doLoadFiles()
+ }
}
-func (this *filesPanel) doLoadFiles() {
- var files []*octoprint.FileInformation
+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
- utils.Logger.Info("Loading list of files from: ", string(this.locationHistory.current()))
+ if this.displayRootLocations() {
+ return nil
+ }
+
+ 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 := &octoprint.FilesRequest{Location: this.locationHistory.current(), Recursive: false}
+ filesRequest := &octoprintApis.FilesRequest {
+ Location: current,
+ Recursive: false,
+ }
filesResponse, err := filesRequest.Do(this.UI.Client)
if err != nil {
- utils.LogError("files.doLoadFiles()", "Do(FilesRequest)", err)
- files = []*octoprint.FileInformation{}
+ logger.LogError("files.getSortedFiles()", "Do(FilesRequest)", err)
+ files = []*dataModels.FileResponse{}
} else {
files = filesResponse.Files
}
- s := byDate(files)
- sort.Sort(s)
+ var filteredFiles []*dataModels.FileResponse
+ for i := range files {
+ if !strings.HasPrefix(files[i].Path, "trash") {
+ filteredFiles = append(filteredFiles, files[i])
+ }
+ }
- utils.EmptyTheContainer(&this.listBox.Container)
+ sortedFiles := utils.FileResponsesSortedByDate(filteredFiles)
+ // sortedFiles := utils.FileResponsesSortedByName(filteredFiles)
+ sort.Sort(sortedFiles)
- for _, fileInformation := range s {
- if fileInformation.IsFolder() {
- this.addFolder(this.listBox, fileInformation)
- }
+ return sortedFiles
+}
+
+func (this *filesPanel) addRootLocations() {
+ this.addMessage("Select source location:")
+ 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)
+
+ listItemBox := this.createListItemBox()
+ listItemBox.Add(topBox)
+
+ listItemFrame, _ := gtk.FrameNew("")
+ listItemFrame.Add(listItemBox)
+
+ this.listBox.Add(listItemFrame)
+}
+
+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))
+ } else {
+ itemImage = utils.MustImageFromFileWithSize("sd.svg", this.Scaled(35), this.Scaled(35))
+ }
+
+ topBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
+ topBox.Add(itemImage)
+
+ name := ""
+ if location == dataModels.Local {
+ name = " OctoPrint"
+ } else {
+ name = " SD Card"
+ }
+ nameLabel := this.createNameLabel(name)
+
+ infoLabel := utils.MustLabel("")
+ infoLabel.SetHAlign(gtk.ALIGN_START)
+ infoLabel.SetMarkup("<small> </small>")
+
+ labelsBox := this.createLabelsBox(nameLabel, infoLabel)
+ topBox.Add(labelsBox)
+
+
+ var actionImage *gtk.Image
+ if location == dataModels.Local {
+ actionImage = this.createOpenLocationImage(0)
+ } else {
+ actionImage = this.createOpenLocationImage(1)
}
- for _, fileInformation := range s {
- if !fileInformation.IsFolder() {
- this.addFile(this.listBox, fileInformation)
+ actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
+ actionBox.Add(actionImage)
+ topBox.Add(actionBox)
+
+ rootLocationButton, _ := gtk.ButtonNew()
+ rootLocationButton.Connect("clicked", func() {
+ this.locationHistory = utils.LocationHistory {
+ Locations: []dataModels.Location{location},
+ }
+
+ this.doLoadFiles()
+ })
+
+ rootLocationButton.Add(topBox)
+
+ return rootLocationButton
+}
+
+func (this *filesPanel) addSortedFiles(sortedFiles []*dataModels.FileResponse) {
+ var index int = 0
+
+ for _, fileResponse := range sortedFiles {
+ if fileResponse.IsFolder() {
+ this.addItem(fileResponse, index)
+ index++
}
}
- this.listBox.ShowAll()
+ for _, fileResponse := range sortedFiles {
+ if !fileResponse.IsFolder() {
+ this.addItem(fileResponse, index)
+ index++
+ }
+ }
}
-func (this *filesPanel) addFile(box *gtk.Box, fileInformation *octoprint.FileInformation) {
- frame, _ := gtk.FrameNew("")
-
- name := utils.MustLabel(fileInformation.Name)
- name.SetMarkup(fmt.Sprintf("<big>%s</big>", utils.StrEllipsis(fileInformation.Name)))
- name.SetHExpand(true)
- name.SetHAlign(gtk.ALIGN_START)
-
- info := utils.MustLabel("")
- info.SetHAlign(gtk.ALIGN_START)
- info.SetMarkup(fmt.Sprintf("<small>Uploaded: <b>%s</b> - Size: <b>%s</b></small>",
- 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-stl.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) 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()
+
+ 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) addFolder(box *gtk.Box, fileInformation *octoprint.FileInformation) {
- frame, _ := gtk.FrameNew("")
+func (this *filesPanel) createInfoAndActionRow(
+ fileResponse *dataModels.FileResponse,
+ index int,
+ isFolder bool,
+) *gtk.Box {
+ infoAndActionRow := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
- labels := utils.MustBox(gtk.ORIENTATION_VERTICAL, 5)
- nameLabel := utils.MustLabel(fileInformation.Name)
- nameLabel.SetMarkup(fmt.Sprintf("<big>%s</big>", utils.StrEllipsis(fileInformation.Name)))
- nameLabel.SetHExpand(true)
- nameLabel.SetHAlign(gtk.ALIGN_START)
- labels.Add(nameLabel)
+ // 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)
- info := utils.MustLabel("")
- info.SetHAlign(gtk.ALIGN_START)
- info.SetMarkup(fmt.Sprintf("<small>Size: <b>%s</b></small>",
- humanize.Bytes(uint64(fileInformation.Size)),
- ))
- labels.Add(info)
- labels.SetVExpand(true)
- labels.SetVAlign(gtk.ALIGN_CENTER)
- labels.SetHAlign(gtk.ALIGN_START)
+ // Column 2: File name and file info
+ name := fileResponse.Name
+ nameLabel := this.createNameLabel(name)
- actionsBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
- actionsBox.Add(this.createOpenFolderButton(fileInformation))
+ infoLabel := utils.MustLabel("")
+ infoLabel.SetHAlign(gtk.ALIGN_START)
+ if isFolder {
+ infoLabel.SetMarkup(fmt.Sprintf("<small>Size: <b>%s</b></small>",
+ humanize.Bytes(uint64(fileResponse.Size)),
+ ))
+ } else {
+ infoLabel.SetMarkup(fmt.Sprintf("<small>Uploaded: <b>%s</b> - Size: <b>%s</b></small>",
+ humanize.Time(fileResponse.Date.Time), humanize.Bytes(uint64(fileResponse.Size)),
+ ))
+ }
+
+ labelsBox := this.createLabelsBox(nameLabel, infoLabel)
+ infoAndActionRow.Add(labelsBox)
- fileBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
- fileBox.SetMarginTop(1)
- fileBox.SetMarginEnd(15)
- fileBox.SetMarginStart(15)
- fileBox.SetMarginBottom(1)
- fileBox.SetHExpand(true)
- image := utils.MustImageFromFileWithSize("folder.svg", this.Scaled(35), this.Scaled(35))
- fileBox.Add(image)
+ // Column 3: printer image
+ var actionImage *gtk.Image
+ if isFolder {
+ actionImage = this.createOpenLocationImage(index)
+ } else {
+ actionImage = this.createPrintImage()
+ }
+
+ actionBox := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
+ actionBox.Add(actionImage)
+
+ infoAndActionRow.Add(actionBox)
+
+ return infoAndActionRow
+}
- fileBox.Add(labels)
- fileBox.Add(actionsBox)
+func (this *filesPanel) createPreviewRow(fileResponse *dataModels.FileResponse) *gtk.Box {
+ previewRow := this.createListItemBox()
+ this.addThumbnail(fileResponse, previewRow)
- frame.Add(fileBox)
- box.Add(frame)
+ return previewRow
}
-func (this *filesPanel) createLoadAndPrintButton(imageFileName string, fileInformation *octoprint.FileInformation) gtk.IWidget {
- 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
+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 {
+ listItemButtonStyleContext.AddClass("list-item-nth-child-even")
+ }
+
+ if isFolder {
+ listItemButton.Connect("clicked", func() {
+ this.locationHistory.GoForward(fileResponse.Name)
+ this.doLoadFiles()
+ })
+ } else {
+ 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"
+ selectFileRequest.Location = this.locationHistory.Locations[0]
+
+ selectFileRequest.Path = fileResponse.Path
selectFileRequest.Print = true
- utils.Logger.Infof("Loading file %q", fileInformation.Name)
+ logger.Infof("Loading file %q", fileResponse.Name)
if err := selectFileRequest.Do(this.UI.Client); err != nil {
- utils.LogError("files.createLoadAndPrintButton()", "Do(SelectFileRequest)", err)
+ logger.LogError("FilesPanel.createLoadAndPrintButton()", "Do(SelectFileRequest)", err)
return
}
- }),
- )
+ }))
+ }
- ctx, _ := button.GetStyleContext()
- ctx.AddClass("color-warning-sign-yellow")
- ctx.AddClass("file-list")
+ return listItemButton
+}
- return button
+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)
+ }
+ 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) 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) createNameLabel(name string) *gtk.Label {
+ nameLabel := utils.MustLabel(name)
+ nameLabel.SetMarkup(fmt.Sprintf("<big>%s</big>", utils.TruncateString(name, 30)))
+ nameLabel.SetHExpand(true)
+ nameLabel.SetHAlign(gtk.ALIGN_START)
+
+ return nameLabel
+}
- ctx, _ := button.GetStyleContext()
- ctx.AddClass("color1")
- ctx.AddClass("file-list")
+func (this *filesPanel) createListItemBox() *gtk.Box {
+ listItemBox := utils.MustBox(gtk.ORIENTATION_VERTICAL, 0)
+ listItemBox.SetMarginTop(0)
+ listItemBox.SetMarginBottom(0)
+ listItemBox.SetMarginStart(0)
+ listItemBox.SetMarginEnd(0)
- return button
+ return listItemBox
}
+func (this *filesPanel) addThumbnail(
+ fileResponse *dataModels.FileResponse,
+ listItemBox *gtk.Box,
+) {
+ if fileResponse.Thumbnail != "" {
+ logger.Debugf("FilesPanel.addItem() - fileResponse.Thumbnail is %s", fileResponse.Thumbnail)
+
+ thumbnailUrl := fmt.Sprintf("%s/%s", os.Getenv(utils.EnvBaseURL), fileResponse.Thumbnail)
+ logger.Debugf("FilesPanel.addItem() - thumbnailPath is: %q" , thumbnailUrl)
+
+ previewImage, imageFromUrlErr := utils.ImageFromUrl(thumbnailUrl)
+ if imageFromUrlErr == nil {
+ logger.Debugf("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")
+
+ // OK, now add the preview image.
+ bottomBox.Add(previewImage)
+
+ // ...and finally add everything to the bottom box/container.
+ listItemBox.Add(bottomBox)
+ }
+ }
+}
+
+func (this *filesPanel) createOpenLocationImage(index int) *gtk.Image {
+ colorClass := fmt.Sprintf("color%d", (index % 4) + 1)
+
+ return this.createActionImage("open.svg", colorClass)
+}
+
+func (this *filesPanel) createPrintImage() *gtk.Image {
+ return this.createActionImage("print.svg", "color-warning-sign-yellow")
+}
+
+func (this *filesPanel) createActionImage(
+ imageFileName string,
+ colorClass string,
+) *gtk.Image {
+ image := utils.MustImageFromFileWithSize(
+ imageFileName,
+ this.Scaled(40),
+ this.Scaled(40),
+ )
+
+ imageStyleContext, _ := image.GetStyleContext()
+ imageStyleContext.AddClass(colorClass)
+
+ return image
+}
+
+
+
/*
func (this *filesPanel) isReady() bool {
state, err := (&octoprint.SDStateRequest{}).Do(this.UI.Client)
diff --git a/ui/HomePanel.go b/ui/HomePanel.go
index 9447ec2..5b26473 100755
--- a/ui/HomePanel.go
+++ b/ui/HomePanel.go
@@ -2,8 +2,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/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", octoprint.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", octoprint.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", octoprint.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/HttpRequestTestWindow.go b/ui/HttpRequestTestWindow.go
new file mode 100755
index 0000000..e4bc00b
--- /dev/null
+++ b/ui/HttpRequestTestWindow.go
@@ -0,0 +1,144 @@
+package ui
+
+import (
+ "fmt"
+ // "io/ioutil"
+ // "os"
+ // "os/user"
+ // "path/filepath"
+ // "strconv"
+ // "strings"
+ "time"
+
+ "github.com/coreos/go-systemd/daemon"
+ "github.com/gotk3/gotk3/gtk"
+
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ // "github.com/Z-Bolt/OctoScreen/ui"
+ "github.com/Z-Bolt/OctoScreen/utils"
+)
+
+
+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 {
+ logger.TraceEnter("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(daemon.SdNotifyReady)
+
+ logger.TraceLeave("CreateHttpRequestTestWindow()")
+ return instance
+}
+
+
+func (this *HttpRequestTestWindow) createWindow(
+ width int,
+ height int,
+) {
+ window, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
+ if err != nil {
+ logger.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() {
+ 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 {
+ logger.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() {
+ logger.TraceEnter("updateTestWindow()")
+
+ this.UpdateCount++
+ strUpdateCount := fmt.Sprintf("UpdateCount: %d", this.UpdateCount)
+ logger.Debug(strUpdateCount)
+ this.Label.SetLabel(strUpdateCount)
+
+
+ //this.checkNotification()
+ this.verifyConnection()
+
+ logger.TraceLeave("updateTestWindow()")
+}
+
+
+func (this *HttpRequestTestWindow) verifyConnection() {
+ logger.TraceEnter("verifyConnection()")
+
+ this.sdNotify(daemon.SdNotifyWatchdog)
+
+ connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(this.Client)
+ if err != nil {
+ logger.LogError("verifyConnection()", "ConnectionRequest.Do()", err)
+ } else {
+ strCurrentState := string(connectionResponse.Current.State)
+ logger.Debugf("verifyConnection() succeeded")
+ logger.Debugf("connectionResponse.Current.State is %q", strCurrentState)
+ }
+
+ logger.TraceLeave("verifyConnection()")
+}
+
+
+func (this *HttpRequestTestWindow) sdNotify(state string) {
+ logger.TraceEnter("sdNotify()")
+
+ _, err := daemon.SdNotify(false, state)
+ if err != nil {
+ logger.Errorf("sdNotify()", "SdNotify()", err)
+ logger.TraceLeave("sdNotify()")
+ return
+ }
+
+ logger.TraceLeave("sdNotify()")
+}
diff --git a/ui/IdleStatusPanel.go b/ui/IdleStatusPanel.go
index 25f85b3..a9bf56f 100755
--- a/ui/IdleStatusPanel.go
+++ b/ui/IdleStatusPanel.go
@@ -1,15 +1,19 @@
package ui
import (
+ // "encoding/json"
// "fmt"
// "sync"
"time"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
+
var idleStatusPanelInstance *idleStatusPanel
type idleStatusPanel struct {
@@ -37,16 +41,32 @@ func IdleStatusPanel(ui *UI) *idleStatusPanel {
}
func (this *idleStatusPanel) initialize() {
+ logger.TraceEnter("IdleStatusPanel.initialize()")
+
defer this.Initialize()
- utils.Logger.Info(this.UI.Settings)
+ logger.Info("IdleStatusPanel.initialize() - settings are:")
+ if this.UI == nil {
+ logger.Error("IdleStatusPanel.initialize() - this.UI is nil")
+ } else if this.UI.Settings == nil {
+ logger.Error("IdleStatusPanel.initialize() - this.UI.Settings is nil")
+ } else {
+ logger.Info("struct values:")
+ logger.Info(this.UI.Settings)
- var menuItems []octoprint.MenuItem
+ jsonStr, err := utils.StructToJson(this.UI.Settings)
+ if err == nil {
+ logger.Info("JSON:")
+ logger.Info(jsonStr)
+ }
+ }
+
+ 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")
+ logger.Info("IdleStatusPanel.initialize() - Loading default menu")
this.UI.Settings.MenuStructure = getDefaultMenuItems(this.UI.Client)
} else {
- utils.Logger.Info("Loading octo menu")
+ logger.Info("IdleStatusPanel.initialize() - Loading octo menu")
}
menuItems = this.UI.Settings.MenuStructure
@@ -61,22 +81,34 @@ func (this *idleStatusPanel) initialize() {
this.Grid().Attach(printButton, 2, 2, 2, 1)
this.showTools()
+
+ logger.TraceLeave("IdleStatusPanel.initialize()")
}
func (this *idleStatusPanel) showFiles() {
+ logger.TraceEnter("IdleStatusPanel.showFiles()")
+
this.UI.GoToPanel(FilesPanel(this.UI, this))
+
+ logger.TraceLeave("IdleStatusPanel.showFiles()")
}
func (this *idleStatusPanel) update() {
+ logger.TraceEnter("IdleStatusPanel.update()")
+
this.updateTemperature()
+
+ logger.TraceLeave("IdleStatusPanel.update()")
}
func (this *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
// 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)
@@ -86,7 +118,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)
@@ -113,16 +145,17 @@ func (this *idleStatusPanel) showTools() {
this.Grid().Attach(this.tool3Button, 1, 1, 1, 1)
this.Grid().Attach(this.bedButton, 0, 2, 2, 1)
}
+
+ logger.TraceLeave("IdleStatusPanel.showTools()")
}
func (this *idleStatusPanel) updateTemperature() {
- utils.Logger.Debug("entering IdleStatusPanel.updateTemperature()")
+ logger.TraceEnter("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)
-
- utils.Logger.Debug("leaving IdleStatusPanel.updateTemperature()")
+ logger.LogError("IdleStatusPanel.updateTemperature()", "Do(StateRequest)", err)
+ logger.TraceLeave("IdleStatusPanel.updateTemperature()")
return
}
@@ -145,5 +178,5 @@ func (this *idleStatusPanel) updateTemperature() {
}
}
- utils.Logger.Debug("leaving IdleStatusPanel.updateTemperature()")
+ logger.TraceLeave("IdleStatusPanel.updateTemperature()")
}
diff --git a/ui/LocationHistory.go b/ui/LocationHistory.go
deleted file mode 100755
index a0a6e67..0000000
--- a/ui/LocationHistory.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package ui
-
-import (
- // "fmt"
- // "sort"
-
- "github.com/mcuadros/go-octoprint"
- // "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
-}
-
-func (l *locationHistory) current() octoprint.Location {
- return l.locations[len(l.locations) - 1]
-}
-
-func (l *locationHistory) goForward(folder string) {
- newLocation := string(l.current()) + "/" + folder
- l.locations = append(l.locations, octoprint.Location(newLocation))
-}
-
-func (l *locationHistory) goBack() {
- l.locations = l.locations[0 : len(l.locations) - 1]
-}
-
-func (l *locationHistory) isRoot() bool {
- if len(l.locations) > 1 {
- return false
- } else {
- return true
- }
-}
diff --git a/ui/MovePanel.go b/ui/MovePanel.go
index 62b534e..f4398d8 100755
--- a/ui/MovePanel.go
+++ b/ui/MovePanel.go
@@ -2,8 +2,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/octoprintApis/dataModels"
"github.com/Z-Bolt/OctoScreen/uiWidgets"
// "github.com/Z-Bolt/OctoScreen/utils"
)
@@ -44,27 +45,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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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/NetworkPanel.go b/ui/NetworkPanel.go
index ce47c68..ffeb016 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 d52bf35..8a82bcb 100755
--- a/ui/PrintStatusPanel.go
+++ b/ui/PrintStatusPanel.go
@@ -6,11 +6,14 @@ import (
"time"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
+
var printStatusPanelInstance *printStatusPanel
type printStatusPanel struct {
@@ -39,7 +42,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()
@@ -69,8 +72,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)
@@ -80,7 +83,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)
@@ -128,7 +131,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")
@@ -156,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")
- cmd := &octoprint.PauseRequest{Action: octoprint.Toggle}
+ 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
@@ -196,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 := (&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)
+ logger.LogError("print_status.updateTemperature()", "Do(StateRequest)", err)
+ logger.TraceLeave("printStatusPanel.updateTemperature()")
return
}
@@ -235,10 +239,10 @@ func (this *printStatusPanel) updateTemperature() {
}
}
- //Logger.Printf("Now leaving print_status.updateTemperature()")
+ logger.TraceLeave("printStatusPanel.updateTemperature()")
}
-func (this *printStatusPanel) doUpdateState(printerState *octoprint.PrinterState) {
+func (this *printStatusPanel) doUpdateState(printerState *dataModels.PrinterState) {
switch {
case printerState.Flags.Printing:
this.pauseButton.SetSensitive(true)
@@ -281,9 +285,9 @@ func (this *printStatusPanel) doUpdateState(printerState *octoprint.PrinterState
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)
@@ -296,11 +300,12 @@ func (this *printStatusPanel) doUpdateState(printerState *octoprint.PrinterState
}
func (this *printStatusPanel) updateJob() {
- //Logger.Printf("Now in print_status.updateJob()")
+ logger.TraceEnter("printStatusPanel.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)
+ logger.LogError("print_status.updateJob()", "Do(JobRequest)", err)
+ logger.TraceLeave("printStatusPanel.updateJob()")
return
}
@@ -308,7 +313,8 @@ 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 = strings.Replace(jobFileName, ".gco", "", -1)
+ jobFileName = utils.TruncateString(jobFileName, 20)
}
this.fileLabel.Label.SetLabel(jobFileName)
@@ -325,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)
@@ -335,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(
@@ -366,9 +372,9 @@ 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 {
- utils.LogError("print_status.confirmStopDialogBox()", "Do(CancelRequest)", err)
+ logger.Warn("Stopping job")
+ if err := (&octoprintApis.CancelRequest{}).Do(printStatusPanel.UI.Client); err != nil {
+ logger.LogError("print_status.confirmStopDialogBox()", "Do(CancelRequest)", err)
return
}
}
diff --git a/ui/SplashPanel.go b/ui/SplashPanel.go
index 00b7ff6..2e3e80e 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,6 +23,8 @@ func NewSplashPanel(ui *UI) *SplashPanel {
}
func (this *SplashPanel) initialize() {
+ logger.TraceEnter("SplashPanel.initialize()")
+
logo := utils.MustImageFromFile("logos/logo.png")
this.Label = utils.MustLabel("...")
this.Label.SetHExpand(true)
@@ -45,9 +48,13 @@ func (this *SplashPanel) initialize() {
box.Add(this.createActionBar())
this.Grid().Add(box)
+
+ logger.TraceLeave("SplashPanel.initialize()")
}
func (this *SplashPanel) createActionBar() gtk.IWidget {
+ logger.TraceEnter("SplashPanel.createActionBar()")
+
actionBar := utils.MustBox(gtk.ORIENTATION_HORIZONTAL, 5)
actionBar.SetHAlign(gtk.ALIGN_END)
@@ -66,29 +73,50 @@ func (this *SplashPanel) createActionBar() gtk.IWidget {
networkButton.SetProperty("width-request", this.Scaled(100))
actionBar.Add(networkButton)
+ logger.TraceLeave("SplashPanel.createActionBar()")
return actionBar
}
func (this *SplashPanel) putOnHold() {
+ logger.TraceEnter("SplashPanel.putOnHold()")
+
this.RetryButton.Show()
- ctx, _ := this.RetryButton.GetStyleContext()
- ctx.RemoveClass("hidden")
+ ctx, err := this.RetryButton.GetStyleContext()
+ if err != nil {
+ logger.LogError("SplashPanel.putOnHold()", "RetryButton.GetStyleContext()", err)
+ } else {
+ ctx.RemoveClass("hidden")
+ }
this.Label.SetText("Cannot connect to the printer. Tap \"Retry\" to try again.")
+
+ logger.TraceLeave("SplashPanel.putOnHold()")
}
func (this *SplashPanel) releaseFromHold() {
+ logger.TraceEnter("SplashPanel.releaseFromHold()")
+
this.RetryButton.Hide()
ctx, _ := this.RetryButton.GetStyleContext()
ctx.AddClass("hidden")
this.Label.SetText("Loading...")
this.UI.connectionAttempts = 0
+
+ logger.TraceLeave("SplashPanel.releaseFromHold()")
}
func (this *SplashPanel) showNetwork() {
+ logger.TraceEnter("SplashPanel.showNetwork()")
+
this.UI.GoToPanel(NetworkPanel(this.UI, this))
+
+ logger.TraceLeave("SplashPanel.showNetwork()")
}
func (this *SplashPanel) showSystem() {
+ logger.TraceEnter("SplashPanel.showSystem()")
+
this.UI.GoToPanel(SystemPanel(this.UI, this))
+
+ logger.TraceLeave("SplashPanel.showSystem()")
}
diff --git a/ui/SystemPanel.go b/ui/SystemPanel.go
index 9e2ce17..e297950 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 27d2cc6..a772079 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 1e5557e..47b6df2 100755
--- a/ui/TemperaturePresetsPanel.go
+++ b/ui/TemperaturePresetsPanel.go
@@ -1,28 +1,32 @@
package ui
import (
- "github.com/mcuadros/go-octoprint"
"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
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
@@ -37,18 +41,20 @@ 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)
+ logger.LogError("TemperaturePresetsPanel.getTemperaturePresets()", "Do(SettingsRequest)", err)
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,
@@ -58,7 +64,6 @@ func (this *temperaturePresetsPanel) createTemperaturePresetButtons() {
}
}
- this.createAllOffButton()
}
func (this *temperaturePresetsPanel) createAllOffButton() {
diff --git a/ui/menu.go b/ui/menu.go
index c6ab921..7e53555 100755
--- a/ui/menu.go
+++ b/ui/menu.go
@@ -3,8 +3,10 @@ package ui
import (
"encoding/json"
- "github.com/mcuadros/go-octoprint"
"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"
)
@@ -12,7 +14,7 @@ import (
func getPanel(
ui *UI,
parentPanel interfaces.IPanel,
- menuItem octoprint.MenuItem,
+ menuItem dataModels.MenuItem,
) interfaces.IPanel {
switch menuItem.Panel {
// The standard "top four" panels that are in the idleStatus panel
@@ -71,35 +73,34 @@ 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
}
}
-func getDefaultMenuItems(client *octoprint.Client) []octoprint.MenuItem {
+func getDefaultMenuItems(client *octoprintApis.Client) []dataModels.MenuItem {
defaultMenuItemsForSingleToolhead := `[
{
"name": "Home",
@@ -206,18 +207,18 @@ func getDefaultMenuItems(client *octoprint.Client) []octoprint.MenuItem {
]`
- var menuItems []octoprint.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)
}
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 c7080d6..dc29fcb 100755
--- a/ui/tool_changer_panel.go
+++ b/ui/tool_changer_panel.go
@@ -4,8 +4,10 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
"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"
)
@@ -55,12 +57,12 @@ 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")
+ 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
}
})
@@ -68,20 +70,20 @@ 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")
+ 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
}
})
}
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)
}
@@ -93,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 ed17ebe..0276fc6 100755
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -10,20 +10,23 @@ 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/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"
)
+
type UI struct {
sync.Mutex
PanelHistory *stack.Stack
- Client *octoprint.Client
- ConnectionState octoprint.ConnectionState
- Settings *octoprint.GetSettingsResponse
+ Client *octoprintApis.Client
+ ConnectionState dataModels.ConnectionState
+ Settings *dataModels.OctoScreenSettingsResponse
UIState string
@@ -44,20 +47,22 @@ 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
height = utils.WindowHeight
}
- instance := &UI{
+ instance := &UI {
PanelHistory: stack.New(),
- Client: octoprint.NewClient(endpoint, key),
+ Client: octoprintApis.NewClient(endpoint, key),
NotificationsBox: uiWidgets.NewNotificationsBox(),
- OctoPrintPluginIsAvailable: true,
+ OctoPrintPluginIsAvailable: false,
Settings: nil,
+ UIState: "__uninitialized__",
+
window: utils.MustWindow(gtk.WINDOW_TOPLEVEL),
time: time.Now(),
@@ -72,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)
}
@@ -98,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()
@@ -114,6 +119,7 @@ func (this *UI) initialize() {
this.window.Connect("show", this.backgroundTask.Start)
this.window.Connect("destroy", func() {
+ logger.Debug("window destroy callback was called, now executing MainQuit()")
gtk.MainQuit()
})
@@ -123,188 +129,238 @@ 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()")
-
- this.sdNotify("WATCHDOG=1")
+ logger.TraceEnter("ui.verifyConnection()")
newUIState := "<<uninitialized-state>>"
splashMessage := "<<uninitialized-message>>"
- 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)
-
- 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"
- if err := (&octoprint.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)
- }
- }
+ logger.Debug("ui.verifyConnection() - ConnectionRequest.Do() succeeded")
+ jsonResponse, err := utils.StructToJson(connectionResponse)
+ if err != nil {
+ logger.Debug("ui.verifyConnection() - utils.StructToJson() failed")
+ } else {
+ 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)", err)
- utils.Logger.Info("ui.verifyConnection() - now setting newUIState to 'splash'")
- newUIState = "splash"
+ logger.LogError("ui.verifyConnection()", "Broke into the else condition because Do(ConnectionRequest) returned an error", err)
+ newUIState, splashMessage = this.getUiStateAndMessageFromError(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)
+ }()
- if strings.Contains(strings.ToLower(errMessage), "deadline exceeded") {
- // Use 'offline' here, but no ending period.
- splashMessage = "Printer is OFFLINE"
+ logger.TraceLeave("ui.verifyConnection()")
+}
+
+
+func (this *UI) getUiStateAndMessageFromConnectionResponse(
+ connectionResponse *dataModels.ConnectionResponse,
+ newUIState string,
+ splashMessage string,
+) (string, string) {
+ logger.TraceEnter("ui.getUiStateAndMessageFromConnectionResponse()")
+
+ strCurrentState := string(connectionResponse.Current.State)
+ logger.Debugf("ui.getUiStateAndMessageFromConnectionResponse() - strCurrentState is %s", strCurrentState)
+
+ switch {
+ case connectionResponse.Current.State.IsOperational():
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is idle")
+ newUIState = "idle"
+ splashMessage = "Initializing..."
+
+ case connectionResponse.Current.State.IsPrinting():
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is printing")
+ newUIState = "printing"
+ splashMessage = "Printing..."
+
+ case connectionResponse.Current.State.IsError():
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state has an error")
+ fallthrough
+ case connectionResponse.Current.State.IsOffline():
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the state is now offline and displaying the splash panel")
+ newUIState = "splash"
+ 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 {
+ logger.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():
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - new state is splash (from IsConnecting)")
+ newUIState = "splash"
+ splashMessage = strCurrentState
+
+ default:
+ logger.Debug("ui.getUiStateAndMessageFromConnectionResponse() - the default case was hit")
+ switch strCurrentState {
+ case "Cancelling":
+ newUIState = "idle"
+
+ default:
+ logger.Errorf("ui.getUiStateAndMessageFromConnectionResponse() - unknown CurrentState: %q", strCurrentState)
}
+ }
+
+ logger.TraceLeave("ui.getUiStateAndMessageFromConnectionResponse()")
+ return newUIState, splashMessage
+}
+
+
+func (this *UI) getUiStateAndMessageFromError(
+ err error,
+ newUIState string,
+ splashMessage string,
+) (string, string) {
+ logger.TraceEnter("ui.getUiStateAndMessageFromError()")
+
+ logger.Info("ui.getUiStateAndMessageFromError() - now setting newUIState to 'splash'")
+ newUIState = "splash"
+
+ if time.Since(this.time) > errMercyPeriod {
+ errMessage := this.errToUser(err)
+
+ 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..."
+ } 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
- }()
+ logger.TraceLeave("ui.getUiStateAndMessageFromError()")
+ return newUIState, splashMessage
+}
+
+
+func (this *UI) setUiState(
+ newUiState string,
+ splashMessage string,
+) {
+ logger.TraceEnter("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 {
+ logger.Infof("ui.setUiState() - newUiState and ui.UIState are the same (%q)", this.UIState)
+ logger.TraceLeave("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)
+ 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 {
+ switch newUiState {
case "idle":
- utils.Logger.Info("ui.verifyConnection() - printer is ready")
+ logger.Info("ui.setUiState() - printer is ready")
this.GoToPanel(IdleStatusPanel(this))
case "printing":
- utils.Logger.Info("ui.verifyConnection() - printing a job")
+ 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)
- }
+ logger.Errorf("ERROR: ui.setUiState() - unknown newUiState case: %q", newUiState)
}
- utils.Logger.Debug("leaving ui.verifyConnection()")
+ 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
}
- notificationRespone, err := (&octoprint.GetNotificationRequest{}).Do(this.Client)
+ 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
}
- 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()")
+ logger.TraceLeave("ui.checkNotification()")
}
func (this *UI) loadSettings() {
- utils.Logger.Debug("entering ui.loadSettings()")
+ logger.TraceEnter("ui.loadSettings()")
- settingsResponse, err := (&octoprint.GetSettingsRequest{}).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") {
// 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
- utils.Logger.Info("The OctoPrint 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()")
+ this.OctoPrintPluginIsAvailable = false
+
+ 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")
+ this.OctoPrintPluginIsAvailable = true
}
if !this.validateMenuItems(settingsResponse.MenuStructure, "", true) {
@@ -313,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 []octoprint.MenuItem, name string, isRoot bool) bool {
+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
}
@@ -344,6 +403,7 @@ func (this *UI) validateMenuItems(menuItems []octoprint.MenuItem, name string, i
)
fatalErrorWindow.ShowAll()
+ logger.TraceLeave("ui.validateMenuItems()")
return false
}
@@ -351,25 +411,30 @@ func (this *UI) validateMenuItems(menuItems []octoprint.MenuItem, name string, i
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()")
+ this.sdNotify(daemon.SdNotifyWatchdog)
+
if this.connectionAttempts > 8 {
+ logger.Info("ui.update() - this.connectionAttempts > 8")
this.splashPanel.putOnHold()
- utils.Logger.Debug("leaving ui.update() - connectionAttempts > 8")
+ logger.TraceLeave("ui.update()")
return
}
- utils.Logger.Infoln("ui.update() - thus.UIState is: ", this.UIState)
+ logger.Infof("ui.update() - this.UIState is: %q", this.UIState)
if this.UIState == "splash" {
this.connectionAttempts++
@@ -381,9 +446,9 @@ func (this *UI) update() {
this.loadSettings()
if this.Settings == nil {
- this.Settings = &octoprint.GetSettingsResponse {
- FilamentInLength: 750.0,
- FilamentOutLength: 800.0,
+ this.Settings = &dataModels.OctoScreenSettingsResponse {
+ FilamentInLength: 100,
+ FilamentOutLength: 100,
ToolChanger: false,
XAxisInverted: false,
YAxisInverted: false,
@@ -399,46 +464,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)
- utils.Logger.Debug("leaving ui.sdNotify()")
- return
+ 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
}
@@ -448,11 +509,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 {
@@ -465,33 +526,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)
- return fmt.Sprintf("Unexpected error: %s", err)
+ 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 2194a90..e0ab17c 100755
--- a/ui/z_offset_calibration_panel.go
+++ b/ui/z_offset_calibration_panel.go
@@ -6,8 +6,10 @@ import (
"time"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
"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"
)
@@ -28,7 +30,7 @@ type zOffsetCalibrationPanel struct {
zOffset float64
// First row
- selectToolStepButton *uiWidgets.SelectToolStepButton
+ selectHotendStepButton *uiWidgets.SelectToolStepButton
decreaseZOffsetButton *uiWidgets.IncreaseZOffsetButton
increaseZOffsetButton *uiWidgets.IncreaseZOffsetButton
@@ -88,22 +90,23 @@ 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 {
+ logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateSelectToolStepButton()", "selectHotendStepButton.Connect()", err)
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()
- utils.Logger.Infof("Changing tool to tool%d", toolheadIndex)
+ toolheadIndex := this.selectHotendStepButton.Index()
+ logger.Infof("Changing tool to tool%d", toolheadIndex)
gcode := fmt.Sprintf("T%d", toolheadIndex)
@@ -114,10 +117,10 @@ 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.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
}
@@ -131,6 +134,7 @@ func (this *zOffsetCalibrationPanel) CreateDecreaseZOffsetButton() {
this.decreaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(false)
_, err := this.decreaseZOffsetButton.Connect("clicked", this.decreaseZOffsetButtonClicked)
if err != nil {
+ logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateDecreaseZOffsetButton()", "decreaseZOffsetButton.Connect()", err)
panic(err)
}
this.Grid().Attach(this.decreaseZOffsetButton, 1, 0, 1, 1)
@@ -148,6 +152,7 @@ func (this *zOffsetCalibrationPanel) CreateIncreaseZOffsetButton() {
this.increaseZOffsetButton = uiWidgets.CreateIncreaseZOffsetButton(true)
_, err := this.increaseZOffsetButton.Connect("clicked", this.increaseZOffsetButtonClicked)
if err != nil {
+ logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateIncreaseZOffsetButton()", "increaseZOffsetButton.Connect()", err)
panic(err)
}
this.Grid().Attach(this.increaseZOffsetButton, 2, 0, 1, 1)
@@ -181,6 +186,7 @@ func (this *zOffsetCalibrationPanel) CreateManualZCalibrationStepButton() {
this.manualZCalibrationStepButton = uiWidgets.CreateManualZCalibrationStepButton()
_, err := this.manualZCalibrationStepButton.Connect("clicked", this.manualZCalibrationStepButtonHandleClick)
if err != nil {
+ logger.LogError("PANIC!!! - zOffsetCalibrationPanel.CreateManualZCalibrationStepButton()", "manualZCalibrationStepButton.Connect()", err)
panic(err)
}
@@ -214,9 +220,9 @@ 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)
+ logger.LogError("z_offset_calibration.createAutoZCalibrationButton()", "Do(RunZOffsetCalibrationRequest)", err)
}
})
}
@@ -228,27 +234,27 @@ 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",
}
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 := &octoprint.SetZOffsetRequest {
+ cmd2 := &octoprintApis.SetZOffsetRequest {
Value: this.zOffset,
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)
}
}
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/AmountToExtrudeStepButton.go b/uiWidgets/AmountToExtrudeStepButton.go
index 758bdb5..08baafb 100755
--- a/uiWidgets/AmountToExtrudeStepButton.go
+++ b/uiWidgets/AmountToExtrudeStepButton.go
@@ -1,6 +1,7 @@
package uiWidgets
import (
+ "github.com/Z-Bolt/OctoScreen/logger"
)
type AmountToExtrudeStepButton struct {
@@ -18,6 +19,7 @@ func CreateAmountToExtrudeStepButton() *AmountToExtrudeStepButton {
Step{" 10mm", "move-step.svg", nil, 10},
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateAmountToExtrudeStepButton()", "CreateStepButton()", err)
panic(err)
}
diff --git a/uiWidgets/AmountToMoveStepButton.go b/uiWidgets/AmountToMoveStepButton.go
index 8613c1d..38430df 100755
--- a/uiWidgets/AmountToMoveStepButton.go
+++ b/uiWidgets/AmountToMoveStepButton.go
@@ -1,6 +1,7 @@
package uiWidgets
import (
+ "github.com/Z-Bolt/OctoScreen/logger"
)
type AmountToMoveStepButton struct {
@@ -18,6 +19,7 @@ func CreateAmountToMoveStepButton() *AmountToMoveStepButton {
Step{" 1mm", "move-step.svg", nil, 1.00},
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateAmountToMoveStepButton()", "CreateStepButton()", err)
panic(err)
}
diff --git a/uiWidgets/CommandButton.go b/uiWidgets/CommandButton.go
index c59a6dd..030d4c8 100755
--- a/uiWidgets/CommandButton.go
+++ b/uiWidgets/CommandButton.go
@@ -4,22 +4,24 @@ import (
// "fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 CommandButton struct {
*gtk.Button
- client *octoprint.Client
+ client *octoprintApis.Client
parentWindow *gtk.Window
- commandDefinition *octoprint.CommandDefinition
+ commandDefinition *dataModels.CommandDefinition
}
func CreateCommandButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
parentWindow *gtk.Window,
- commandDefinition *octoprint.CommandDefinition,
+ commandDefinition *dataModels.CommandDefinition,
iconName string,
) *CommandButton {
base := utils.MustButtonImage(utils.StrEllipsisLen(commandDefinition.Name, 16), iconName + ".svg", nil)
@@ -31,6 +33,7 @@ func CreateCommandButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateCommandButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -39,21 +42,26 @@ func CreateCommandButton(
func (this *CommandButton) handleClicked() {
if len(this.commandDefinition.Confirm) != 0 {
- utils.MustConfirmDialogBox(this.parentWindow, this.commandDefinition.Confirm, this.sendCommand)
- return
+ utils.MustConfirmDialogBox(
+ this.parentWindow,
+ this.commandDefinition.Confirm,
+ this.sendCommand,
+ )()
} else {
this.sendCommand()
}
}
func (this *CommandButton) sendCommand() {
- commandRequest := &octoprint.SystemExecuteCommandRequest{
- Source: octoprint.Custom,
+ 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 {
- 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 8b36d49..232abed 100755
--- a/uiWidgets/ControlButton.go
+++ b/uiWidgets/ControlButton.go
@@ -4,22 +4,24 @@ import (
// "fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 ControlButton struct {
*gtk.Button
- client *octoprint.Client
+ client *octoprintApis.Client
parentWindow *gtk.Window
- controlDefinition *octoprint.ControlDefinition
+ controlDefinition *dataModels.ControlDefinition
}
func CreateControlButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
parentWindow *gtk.Window,
- controlDefinition *octoprint.ControlDefinition,
+ controlDefinition *dataModels.ControlDefinition,
iconName string,
) *ControlButton {
base := utils.MustButtonImage(utils.StrEllipsisLen(controlDefinition.Name, 16), iconName + ".svg", nil)
@@ -31,6 +33,7 @@ func CreateControlButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateControlButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -39,15 +42,20 @@ func CreateControlButton(
func (this *ControlButton) handleClicked() {
if len(this.controlDefinition.Confirm) != 0 {
- utils.MustConfirmDialogBox(this.parentWindow, this.controlDefinition.Confirm, this.sendCommand)
- return
+ utils.MustConfirmDialogBox(
+ this.parentWindow,
+ this.controlDefinition.Confirm,
+ this.sendCommand,
+ )()
} else {
this.sendCommand()
}
}
func (this *ControlButton) sendCommand() {
- commandRequest := &octoprint.CommandRequest{
+ logger.Infof("ControlButton.sendCommand(), now sending command %q", this.controlDefinition.Name)
+
+ commandRequest := &octoprintApis.CommandRequest{
Commands: this.controlDefinition.Commands,
}
@@ -55,9 +63,8 @@ func (this *ControlButton) sendCommand() {
commandRequest.Commands = []string{this.controlDefinition.Command}
}
- utils.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 f10a5cb..8f00e54 100755
--- a/uiWidgets/CoolDownButton.go
+++ b/uiWidgets/CoolDownButton.go
@@ -4,20 +4,21 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 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)
@@ -29,6 +30,7 @@ func CreateCoolDownButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateCoolDownButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -44,23 +46,29 @@ 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)
+ logger.LogError("CoolDownButton.handleClicked()", "Do(BedTargetRequest)", err)
return
}
// 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}}
+ 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)
+ logger.LogError("TemperaturePresetsPanel.setTemperaturesToPreset()", "Do(ToolTargetRequest)", err)
}
}
}
diff --git a/uiWidgets/FanButton.go b/uiWidgets/FanButton.go
index 3289002..ad5de56 100755
--- a/uiWidgets/FanButton.go
+++ b/uiWidgets/FanButton.go
@@ -4,19 +4,21 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 FanButton struct {
*gtk.Button
- client *octoprint.Client
+ client *octoprintApis.Client
amount int
}
func CreateFanButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
amount int,
) *FanButton {
var (
@@ -40,6 +42,7 @@ func CreateFanButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateFanButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -47,13 +50,13 @@ func CreateFanButton(
}
func (this *FanButton) handleClicked() {
- cmd := &octoprint.CommandRequest{}
+ cmd := &octoprintApis.CommandRequest{}
cmd.Commands = []string{
fmt.Sprintf("M106 S%d", (255 * this.amount / 100)),
}
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 c3386ce..858a702 100755
--- a/uiWidgets/FilamentExtrudeButton.go
+++ b/uiWidgets/FilamentExtrudeButton.go
@@ -2,7 +2,9 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -10,19 +12,19 @@ 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
+ selectExtruderStepButton *SelectToolStepButton
isForward bool
}
func CreateFilamentExtrudeButton(
parentWindow *gtk.Window,
- client *octoprint.Client,
+ 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
@@ -38,11 +40,12 @@ func CreateFilamentExtrudeButton(
client: client,
amountToExtrudeStepButton: amountToExtrudeStepButton,
flowRateStepButton: flowRateStepButton,
- selectToolStepButton: selectToolStepButton,
+ selectExtruderStepButton: selectExtruderStepButton,
isForward: isForward,
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateFilamentExtrudeButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -53,37 +56,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.selectExtruderStepButton.Value()
- 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 := &octoprint.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 caf953b..79dfb2c 100755
--- a/uiWidgets/FilamentLoadButton.go
+++ b/uiWidgets/FilamentLoadButton.go
@@ -1,25 +1,34 @@
package uiWidgets
import (
+ // "fmt"
+
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 FilamentLoadButton struct {
*gtk.Button
parentWindow *gtk.Window
- client *octoprint.Client
- selectToolStepButton *SelectToolStepButton
+ client *octoprintApis.Client
+ flowRateStepButton *FlowRateStepButton // The flow rate step button is optional.
+ selectExtruderStepButton *SelectToolStepButton
isForward bool
+ length int
}
func CreateFilamentLoadButton(
parentWindow *gtk.Window,
- client *octoprint.Client,
- selectToolStepButton *SelectToolStepButton,
+ client *octoprintApis.Client,
+ flowRateStepButton *FlowRateStepButton, // The flow rate step button is optional.
+ selectExtruderStepButton *SelectToolStepButton,
isForward bool,
+ length int,
) *FilamentLoadButton {
var base *gtk.Button
if isForward {
@@ -32,11 +41,14 @@ func CreateFilamentLoadButton(
Button: base,
parentWindow: parentWindow,
client: client,
- selectToolStepButton: selectToolStepButton,
+ flowRateStepButton: flowRateStepButton,
+ selectExtruderStepButton: selectExtruderStepButton,
isForward: isForward,
+ length: length,
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateFilamentLoadButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -48,29 +60,19 @@ 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
- }
+ extruderId := this.selectExtruderStepButton.Value()
- // BUG: This does not work. At least not on a Prusa i3. Need to get this working with all printers.
- cmd := &octoprint.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 85ad50f..c665875 100755
--- a/uiWidgets/FlowRateStepButton.go
+++ b/uiWidgets/FlowRateStepButton.go
@@ -1,17 +1,19 @@
package uiWidgets
import (
- "github.com/mcuadros/go-octoprint"
+ "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 FlowRateStepButton struct {
*StepButton
- client *octoprint.Client
+ client *octoprintApis.Client
}
func CreateFlowRateStepButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
) *FlowRateStepButton {
base, err := CreateStepButton(
1,
@@ -20,6 +22,7 @@ func CreateFlowRateStepButton(
Step{"Slow (75%)", "speed-slow.svg", nil, 75},
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateFlowRateStepButton()", "CreateStepButton()", err)
panic(err)
}
@@ -36,14 +39,5 @@ func (this *FlowRateStepButton) Value() int {
}
func (this *FlowRateStepButton) SendChangeFlowRate() error {
- cmd := &octoprint.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 c1c62fe..b36f848 100755
--- a/uiWidgets/HomeAllButton.go
+++ b/uiWidgets/HomeAllButton.go
@@ -2,18 +2,20 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 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)
@@ -23,6 +25,7 @@ func CreateHomeAllButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateHomeAllButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -30,18 +33,18 @@ func CreateHomeAllButton(
}
func (this *HomeAllButton) handleClicked() {
- utils.Logger.Infof("Homing the print head")
+ logger.Infof("Homing the print head")
// Version A:
- axes := []octoprint.Axis {
- octoprint.XAxis,
- octoprint.YAxis,
- octoprint.ZAxis,
+ axes := []dataModels.Axis {
+ dataModels.XAxis,
+ dataModels.YAxis,
+ dataModels.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)
+ logger.LogError("HomeAllButton.handleClicked()", "Do(PrintHeadHomeRequest)", err)
}
@@ -55,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 b67bee3..5733798 100755
--- a/uiWidgets/HomeButton.go
+++ b/uiWidgets/HomeButton.go
@@ -2,22 +2,24 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 HomeButton struct {
*gtk.Button
- client *octoprint.Client
- axes []octoprint.Axis
+ client *octoprintApis.Client
+ axes []dataModels.Axis
}
func CreateHomeButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
buttonLabel string,
imageFileName string,
- axes ...octoprint.Axis,
+ axes ...dataModels.Axis,
) *HomeButton {
base := utils.MustButtonImageStyle(buttonLabel, imageFileName, "", nil)
@@ -28,6 +30,7 @@ func CreateHomeButton(
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateHomeButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -35,10 +38,10 @@ func CreateHomeButton(
}
func (this *HomeButton) handleClicked() {
- cmd := &octoprint.PrintHeadHomeRequest{Axes: this.axes}
- utils.Logger.Infof("Homing the print head in %s axes", this.axes)
+ cmd := &octoprintApis.PrintHeadHomeRequest{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/IncreaseZOffsetButton.go b/uiWidgets/IncreaseZOffsetButton.go
index 0ec26b2..0c598e7 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/ManualZCalibrationStepButton.go b/uiWidgets/ManualZCalibrationStepButton.go
index ed2d099..b9b6614 100755
--- a/uiWidgets/ManualZCalibrationStepButton.go
+++ b/uiWidgets/ManualZCalibrationStepButton.go
@@ -1,6 +1,7 @@
package uiWidgets
import (
+ "github.com/Z-Bolt/OctoScreen/logger"
)
type ManualZCalibrationStepButton struct {
@@ -14,6 +15,7 @@ func CreateManualZCalibrationStepButton() *ManualZCalibrationStepButton {
Step{"Stop Manual\nZ Calibration", "z-calibration.svg", nil, true},
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateManualZCalibrationStepButton()", "CreateStepButton()", err)
panic(err)
}
diff --git a/uiWidgets/MoveButton.go b/uiWidgets/MoveButton.go
index f3675f8..7eb4a4d 100755
--- a/uiWidgets/MoveButton.go
+++ b/uiWidgets/MoveButton.go
@@ -2,25 +2,26 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
- "github.com/Z-Bolt/OctoScreen/utils"
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
)
type MoveButton struct {
*gtk.Button
- client *octoprint.Client
+ client *octoprintApis.Client
amountToMoveStepButton *AmountToMoveStepButton
- axis octoprint.Axis
+ axis dataModels.Axis
direction float64
}
func CreateMoveButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
amountToMoveStepButton *AmountToMoveStepButton,
label string,
image string,
- axis octoprint.Axis,
+ axis dataModels.Axis,
direction float64,
) *MoveButton {
// A little bit of a "chicken or the egg" situation here. Create the
@@ -41,20 +42,20 @@ 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 dataModels.XAxis:
cmd.X = distance
- case octoprint.YAxis:
+ case dataModels.YAxis:
cmd.Y = distance
- case octoprint.ZAxis:
+ case dataModels.ZAxis:
cmd.Z = distance
}
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 da5bb70..db04721 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"
)
@@ -18,9 +19,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 {
+ logger.LogError("PANIC!!! - MustPressedButton()", "gtk.ButtonNewWithLabel()", err)
+ panic(err)
}
button.SetImage(image)
diff --git a/uiWidgets/OctoPrintInfoBox.go b/uiWidgets/OctoPrintInfoBox.go
index 34ae63d..dd82a82 100755
--- a/uiWidgets/OctoPrintInfoBox.go
+++ b/uiWidgets/OctoPrintInfoBox.go
@@ -3,7 +3,9 @@ package uiWidgets
import (
"fmt"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -13,23 +15,31 @@ 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)
+ server := ""
+ apiVersion := ""
+ versionResponse, err := (&octoprintApis.VersionRequest{}).Do(client)
if err != nil {
- panic(err)
+ logger.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),
+ server,
+ fmt.Sprintf("(API %s)", apiVersion), // Use 3 spaces... 1 space doesn't have enough kerning.
)
instance := &OctoPrintInfoBox {
diff --git a/uiWidgets/OctoScreenInfoBox.go b/uiWidgets/OctoScreenInfoBox.go
index 4cab3dd..fac2270 100755
--- a/uiWidgets/OctoScreenInfoBox.go
+++ b/uiWidgets/OctoScreenInfoBox.go
@@ -4,7 +4,8 @@ import (
// "fmt"
"strings"
- "github.com/mcuadros/go-octoprint"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
"github.com/Z-Bolt/OctoScreen/utils"
)
@@ -13,7 +14,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 d32060e..8cf1ce5 100755
--- a/uiWidgets/OctoScreenPluginInfoBox.go
+++ b/uiWidgets/OctoScreenPluginInfoBox.go
@@ -3,7 +3,9 @@ package uiWidgets
import (
// "fmt"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -12,7 +14,8 @@ type OctoScreenPluginInfoBox struct {
}
func CreateOctoScreenPluginInfoBox(
- client *octoprint.Client,
+ client *octoprintApis.Client,
+ uiState string,
octoPrintPluginIsInstalled bool,
) *OctoScreenPluginInfoBox {
logoImage := utils.MustImageFromFile("logos/puzzle-piece.png")
@@ -20,24 +23,25 @@ func CreateOctoScreenPluginInfoBox(
str2 := ""
if octoPrintPluginIsInstalled {
- getPluginManagerInfoResponse, err := (&octoprint.GetPluginManagerInfoRequest{}).Do(client)
+ pluginManagerInfoResponse, err := (&octoprintApis.PluginManagerInfoRequest{}).Do(client, uiState)
if err != nil {
- panic(err)
- }
-
- found := false
- for i := 0; i < len(getPluginManagerInfoResponse.Plugins) && !found; i++ {
- plugin := getPluginManagerInfoResponse.Plugins[i]
- if plugin.Key == "zbolt_octoscreen" {
- found = true
- str2 = plugin.Version
+ logger.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 90b8044..d42a9cf 100755
--- a/uiWidgets/SelectToolStepButton.go
+++ b/uiWidgets/SelectToolStepButton.go
@@ -5,7 +5,9 @@ import (
"strconv"
"strings"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -13,29 +15,71 @@ type SelectToolStepButton struct {
*StepButton
}
-func CreateSelectToolStepButton(
- client *octoprint.Client,
+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++ {
- var step Step
- if i == 0 && toolheadCount == 1 {
- step = Step {
- "Hotend",
- utils.GetHotendFileName(1, toolheadCount),
- nil,
- "tool0",
- }
+ for i := 0; i < extruderCount; i++ {
+ label := ""
+ if i == 0 && extruderCount == 1 {
+ label = "Extruder"
} else {
- step = Step {
- fmt.Sprintf("Hotend %d", i + 1),
- utils.GetHotendFileName(i + 1, toolheadCount),
- 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)
+ }
+
+ if includeBed {
+ steps = append(steps, Step{"Bed", "bed.svg", nil, "bed"})
+ }
+
+ base, err := CreateStepButton(
+ 1,
+ steps...,
+ )
+ if err != nil {
+ logger.LogError("PANIC!!! - CreateSelectExtruderStepButton()", "CreateStepButton()", err)
+ 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++ {
+ label := ""
+ if i == 0 && hotendCount == 1 {
+ label = "Hotend"
+ } else {
+ 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)
@@ -50,6 +94,7 @@ func CreateSelectToolStepButton(
steps...,
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateSelectHotendStepButton()", "CreateStepButton()", err)
panic(err)
}
@@ -60,6 +105,9 @@ func CreateSelectToolStepButton(
return instance
}
+
+
+
func (this *SelectToolStepButton) Value() string {
return this.StepButton.Value().(string)
}
diff --git a/uiWidgets/StepButton.go b/uiWidgets/StepButton.go
index 0269f65..ca20ab3 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,6 +27,7 @@ type StepButton struct {
func CreateStepButton(colorVariation int, steps ...Step) (*StepButton, error) {
if 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 b6218ce..134a5d3 100755
--- a/uiWidgets/SystemCommandButton.go
+++ b/uiWidgets/SystemCommandButton.go
@@ -4,7 +4,9 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -13,18 +15,19 @@ 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 {
+ logger.LogError("PANIC!!! - CreateSystemCommandButton()", "SystemCommandsRequest.Do()", err)
panic(err)
}
- var cmd *octoprint.CommandDefinition
+ var cmd *dataModels.CommandDefinition
var cb func()
for _, commandDefinition := range systemCommandsResponse.Core {
@@ -35,13 +38,13 @@ func CreateSystemCommandButton(
if cmd != nil {
do := func() {
- systemExecuteCommandRequest := &octoprint.SystemExecuteCommandRequest{
- Source: octoprint.Core,
+ systemExecuteCommandRequest := &octoprintApis.SystemExecuteCommandRequest{
+ Source: dataModels.Core,
Action: cmd.Action,
}
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 86e858b..244cd49 100755
--- a/uiWidgets/SystemInfoBox.go
+++ b/uiWidgets/SystemInfoBox.go
@@ -4,7 +4,9 @@ import (
// "fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
@@ -13,7 +15,7 @@ type SystemInfoBox struct {
}
func CreateSystemInfoBox(
- client *octoprint.Client,
+ client *octoprintApis.Client,
image *gtk.Image,
str1 string,
str2 string,
@@ -40,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 4f9e719..802d2c2 100755
--- a/uiWidgets/SystemInformationInfoBox.go
+++ b/uiWidgets/SystemInformationInfoBox.go
@@ -7,9 +7,8 @@ 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/logger"
"github.com/Z-Bolt/OctoScreen/utils"
)
@@ -43,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 72529e2..d75f1c3 100755
--- a/uiWidgets/TemperatureAmountStepButton.go
+++ b/uiWidgets/TemperatureAmountStepButton.go
@@ -1,6 +1,7 @@
package uiWidgets
import (
+ "github.com/Z-Bolt/OctoScreen/logger"
)
type TemperatureAmountStepButton struct {
@@ -17,6 +18,7 @@ func CreateTemperatureAmountStepButton() *TemperatureAmountStepButton {
Step{" 5°C", "move-step.svg", nil, 5.0},
)
if err != nil {
+ logger.LogError("PANIC!!! - CreateTemperatureAmountStepButton()", "CreateStepButton()", err)
panic(err)
}
diff --git a/uiWidgets/TemperatureIncreaseButton.go b/uiWidgets/TemperatureIncreaseButton.go
index 6a7d717..ba4a1a4 100755
--- a/uiWidgets/TemperatureIncreaseButton.go
+++ b/uiWidgets/TemperatureIncreaseButton.go
@@ -2,23 +2,25 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 TemperatureIncreaseButton struct {
*gtk.Button
- client *octoprint.Client
+ client *octoprintApis.Client
temperatureAmountStepButton *TemperatureAmountStepButton
- selectToolStepButton *SelectToolStepButton
+ selectHotendStepButton *SelectToolStepButton
isIncrease bool
}
func CreateTemperatureIncreaseButton(
- client *octoprint.Client,
+ client *octoprintApis.Client,
temperatureAmountStepButton *TemperatureAmountStepButton,
- selectToolStepButton *SelectToolStepButton,
+ selectHotendStepButton *SelectToolStepButton,
isIncrease bool,
) *TemperatureIncreaseButton {
var base *gtk.Button
@@ -32,11 +34,12 @@ func CreateTemperatureIncreaseButton(
Button: base,
client: client,
temperatureAmountStepButton: temperatureAmountStepButton,
- selectToolStepButton: selectToolStepButton,
+ selectHotendStepButton: selectHotendStepButton,
isIncrease: isIncrease,
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateTemperatureIncreaseButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -45,10 +48,10 @@ 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)
+ logger.LogError("TemperatureIncreaseButton.handleClicked()", "GetToolTarget()", err)
return
}
@@ -65,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 ebf1189..c59ed3d 100755
--- a/uiWidgets/TemperaturePresetButton.go
+++ b/uiWidgets/TemperaturePresetButton.go
@@ -2,25 +2,27 @@ package uiWidgets
import (
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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 TemperaturePresetButton struct {
*gtk.Button
- client *octoprint.Client
- selectToolStepButton *SelectToolStepButton
+ client *octoprintApis.Client
+ selectHotendStepButton *SelectToolStepButton
imageFileName string
- temperaturePreset *octoprint.TemperaturePreset
+ temperaturePreset *dataModels.TemperaturePreset
callback func()
}
func CreateTemperaturePresetButton(
- client *octoprint.Client,
- selectToolStepButton *SelectToolStepButton,
+ client *octoprintApis.Client,
+ selectHotendStepButton *SelectToolStepButton,
imageFileName string,
- temperaturePreset *octoprint.TemperaturePreset,
+ temperaturePreset *dataModels.TemperaturePreset,
callback func(),
) *TemperaturePresetButton {
presetName := utils.StrEllipsisLen(temperaturePreset.Name, 10)
@@ -29,13 +31,14 @@ func CreateTemperaturePresetButton(
instance := &TemperaturePresetButton{
Button: base,
client: client,
- selectToolStepButton: selectToolStepButton,
+ selectHotendStepButton: selectHotendStepButton,
imageFileName: imageFileName,
temperaturePreset: temperaturePreset,
callback: callback,
}
_, err := instance.Button.Connect("clicked", instance.handleClicked)
if err != nil {
+ logger.LogError("PANIC!!! - CreateTemperaturePresetButton()", "instance.Button.Connect()", err)
panic(err)
}
@@ -43,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.selectToolStepButton.Value()
+ 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"
}
@@ -63,28 +66,42 @@ 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.
- 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)
+ logger.LogError("TemperaturePresetButton.handleClicked()", "Do(BedTargetRequest)", err)
return
}
// 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)
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 6cd3e18..53556f9 100755
--- a/uiWidgets/TemperatureStatusBox.go
+++ b/uiWidgets/TemperatureStatusBox.go
@@ -4,8 +4,10 @@ import (
// "time"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
"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"
)
@@ -13,23 +15,23 @@ 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 {
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
}
@@ -44,9 +46,9 @@ func CreateTemperatureStatusBox(
instance.SetVAlign(gtk.ALIGN_CENTER)
instance.SetHAlign(gtk.ALIGN_CENTER)
- var bedTemperatureData *octoprint.TemperatureData = nil
+ 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
@@ -80,7 +82,7 @@ func CreateTemperatureStatusBox(
}
// interfaces.ITemperatureDataDisplay
-func (this *TemperatureStatusBox) UpdateTemperatureData(currentTemperatureData map[string]octoprint.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 da3b3e7..42fa821 100755
--- a/uiWidgets/ToolButton.go
+++ b/uiWidgets/ToolButton.go
@@ -5,12 +5,13 @@ import (
"sync"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "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"
)
-
func ToolImageFileName(
index int,
) string {
@@ -43,12 +44,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)
@@ -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
@@ -78,7 +79,7 @@ func (this *ToolButton) UpdateStatus(heating bool) {
this.isHeating = heating
}
-func (this *ToolButton) SetTemperatures(temperatureData octoprint.TemperatureData) {
+func (this *ToolButton) SetTemperatures(temperatureData dataModels.TemperatureData) {
text := utils.GetTemperatureDataString(temperatureData)
this.SetLabel(text)
this.UpdateStatus(temperatureData.Target > 0)
@@ -87,9 +88,9 @@ 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)
+ logger.LogError("ToolButton.GetProfileTemperature()", "Do(SettingsRequest)", err)
return 0
}
@@ -127,16 +128,16 @@ 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)
+ logger.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)
+ logger.LogError("ToolButton.clicked()", "Do(ToolTargetRequest)", err)
}
}
}
diff --git a/uiWidgets/ToolPrintingButon.go b/uiWidgets/ToolPrintingButon.go
index 8133e8e..662d1d1 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/background_task.go b/utils/BackgroundTask.go
index a01d444..989dda8 100755
--- a/utils/background_task.go
+++ b/utils/BackgroundTask.go
@@ -5,8 +5,10 @@ import (
"sync"
"github.com/gotk3/gotk3/glib"
+ "github.com/Z-Bolt/OctoScreen/logger"
)
+
type BackgroundTask struct {
sync.Mutex
@@ -34,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
@@ -62,7 +64,7 @@ func (this *BackgroundTask) loop() {
this.execute()
case <-this.close:
- Logger.Info("Background task closed")
+ logger.Info("Background task closed")
return
}
}
@@ -71,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/FileResponsesSortedByDate.go b/utils/FileResponsesSortedByDate.go
new file mode 100755
index 0000000..dae8fb7
--- /dev/null
+++ b/utils/FileResponsesSortedByDate.go
@@ -0,0 +1,25 @@
+package utils
+
+import (
+ // "fmt"
+ // "sort"
+
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+ // "github.com/Z-Bolt/OctoScreen/uiWidgets"
+)
+
+
+type FileResponsesSortedByDate []*dataModels.FileResponse
+
+func (this FileResponsesSortedByDate) Len() int {
+ return len(this)
+}
+
+func (this FileResponsesSortedByDate) Swap(i, j int) {
+ this[i], this[j] = this[j], this[i]
+}
+
+func (this FileResponsesSortedByDate) Less(i, j int) bool {
+ return this[j].Date.Time.Before(this[i].Date.Time)
+}
diff --git a/utils/FileResponsesSortedByName.go b/utils/FileResponsesSortedByName.go
new file mode 100755
index 0000000..b05dd5e
--- /dev/null
+++ b/utils/FileResponsesSortedByName.go
@@ -0,0 +1,26 @@
+package utils
+
+import (
+ // "fmt"
+ // "sort"
+ // "strings"
+
+ // "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
+ // "github.com/Z-Bolt/OctoScreen/uiWidgets"
+)
+
+
+type FileResponsesSortedByName []*dataModels.FileResponse
+
+func (this FileResponsesSortedByName) Len() int {
+ return len(this)
+}
+
+func (this FileResponsesSortedByName) Swap(i, j int) {
+ this[i], this[j] = this[j], this[i]
+}
+
+func (this FileResponsesSortedByName) Less(i, j int) bool {
+ return this[j].Name > this[i].Name
+}
diff --git a/utils/LocationHistory.go b/utils/LocationHistory.go
new file mode 100755
index 0000000..47aca45
--- /dev/null
+++ b/utils/LocationHistory.go
@@ -0,0 +1,46 @@
+package utils
+
+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"
+)
+
+type LocationHistory struct {
+ Locations []dataModels.Location
+}
+
+func (this *LocationHistory) Length() int {
+ return len(this.Locations)
+}
+
+func (this *LocationHistory) CurrentLocation() dataModels.Location {
+ length := this.Length()
+ if length < 1 {
+ logger.Error("CurrentLocation() - length < 1")
+ panic("PANIC!!! - LocationHistory.current() - locations is empty")
+ }
+
+ return this.Locations[length - 1]
+}
+
+func (this *LocationHistory) GoForward(folder string) {
+ newLocation := string(this.CurrentLocation()) + "/" + folder
+ this.Locations = append(this.Locations, dataModels.Location(newLocation))
+}
+
+func (this *LocationHistory) GoBack() {
+ this.Locations = this.Locations[0 : len(this.Locations) - 1]
+}
+
+func (this *LocationHistory) IsRoot() bool {
+ if len(this.Locations) > 1 {
+ return false
+ } else {
+ return true
+ }
+}
diff --git a/utils/UpdateTemperaturesBackgroundTask.go b/utils/UpdateTemperaturesBackgroundTask.go
index e5ad09c..35ea979 100755
--- a/utils/UpdateTemperaturesBackgroundTask.go
+++ b/utils/UpdateTemperaturesBackgroundTask.go
@@ -3,19 +3,25 @@ package utils
import (
"time"
- "github.com/mcuadros/go-octoprint"
"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"
)
-// TODO: convert this into a singleton class
+
+// TODO: convert this into a singleton
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")
+ logger.Error("UpdateTemperaturesBackgroundTask.CreateUpdateTemperaturesBackgroundTask() - updateTemperaturesBackgroundTask has already been set")
return
}
@@ -24,19 +30,29 @@ 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
}
func updateTemperaturesCallback() {
+ logger.TraceEnter("UpdateTemperaturesBackgroundTask.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)
- 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 f4f038b..9fb6a59 100755
--- a/utils/environment.go
+++ b/utils/environment.go
@@ -4,8 +4,15 @@ import (
"fmt"
"os"
//"strings"
+
+
+ "github.com/Z-Bolt/OctoScreen/logger"
)
+
+const MISSING_ENV_TOKEN = ">>MISSING<<"
+const INVALID_ENV_TOKEN = "!!!INVALID!!!"
+
// Required environment variables
const (
EnvStylePath = "OCTOSCREEN_STYLE_PATH"
@@ -76,46 +83,55 @@ 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!
+ // 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
- 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) {
value := os.Getenv(key)
if value == "" {
- value = ">>MISSING<<"
+ value = MISSING_ENV_TOKEN
}
- Logger.Infof("key: %q, value: %q", key, value)
+ logger.Infof("key: %q, value: %q", key, value)
}
func dumpObfuscatedEnvironmentVariable(key string) {
value := os.Getenv(key)
if value == "" {
- value = ">>MISSING<<"
+ value = MISSING_ENV_TOKEN
+ } 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 {
@@ -123,16 +139,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
diff --git a/utils/filament.go b/utils/filament.go
new file mode 100755
index 0000000..a2145fc
--- /dev/null
+++ b/utils/filament.go
@@ -0,0 +1,72 @@
+package utils
+
+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"
+)
+
+
+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 {
+ logger.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 {
+ logger.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 {
+ logger.LogError("filament.SetFlowRate()", "Go(ToolFlowRateRequest)", err)
+ return err
+ }
+
+ return nil
+}
diff --git a/utils/file.go b/utils/file_utils.go
index 94ef6d6..d015095 100755
--- a/utils/file.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/gtk.go b/utils/gtk.go
index 797851e..67d041e 100755
--- a/utils/gtk.go
+++ b/utils/gtk.go
@@ -1,17 +1,22 @@
package utils
import (
+ "bytes"
+ "errors"
"fmt"
+ "net/http"
"path/filepath"
"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 {
+ logger.LogError("PANIC!!! - MustWindow()", "gtk.WindowNew()", err)
panic(err)
}
@@ -24,6 +29,7 @@ func MustWindow(windowType gtk.WindowType) *gtk.Window {
func MustGrid() *gtk.Grid {
grid, err := gtk.GridNew()
if err != nil {
+ logger.LogError("PANIC!!! - MustGrid()", "gtk.GridNew()", err)
panic(err)
}
@@ -34,6 +40,7 @@ func MustGrid() *gtk.Grid {
func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box {
box, err := gtk.BoxNew(orientation, spacing)
if err != nil {
+ logger.LogError("PANIC!!! - MustBox()", "gtk.BoxNew()", err)
panic(err)
}
@@ -44,6 +51,7 @@ func MustBox(orientation gtk.Orientation, spacing int) *gtk.Box {
func MustProgressBar() *gtk.ProgressBar {
progressBar, err := gtk.ProgressBarNew()
if err != nil {
+ logger.LogError("PANIC!!! - MustProgressBar()", "gtk.ProgressBarNew()", err)
panic(err)
}
@@ -54,6 +62,7 @@ func MustProgressBar() *gtk.ProgressBar {
func MustLabel(format string, args ...interface{}) *gtk.Label {
label, err := gtk.LabelNew("")
if err != nil {
+ logger.LogError("PANIC!!! - MustLabel()", "gtk.LabelNew()", err)
panic(err)
}
@@ -66,6 +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 {
+ logger.LogError("PANIC!!! - MustLabelWithCssClass()", "gtk.LabelNew()", err)
panic(err)
}
@@ -81,6 +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 {
+ logger.LogError("PANIC!!! - MustLabelWithCssClasses()", "gtk.LabelNew()", err)
panic(err)
}
@@ -127,6 +138,7 @@ func MustButtonImage(buttonlabel, imageFileName string, clicked func()) *gtk.But
image := MustImageFromFile(imageFileName)
button, err := gtk.ButtonNewWithLabel(buttonlabel)
if err != nil {
+ logger.LogError("PANIC!!! - MustButtonImage()", "gtk.ButtonNewWithLabel()", err)
panic(err)
}
@@ -147,6 +159,7 @@ func MustToggleButton(label string, imageFileName string, clicked func()) *gtk.T
image := MustImageFromFile(imageFileName)
button, err := gtk.ToggleButtonNewWithLabel(label)
if err != nil {
+ logger.LogError("PANIC!!! - MustToggleButton()", "gtk.ToggleButtonNewWithLabel()", err)
panic(err)
}
@@ -166,6 +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 {
+ logger.LogError("PANIC!!! - MustButton()", "gtk.ButtonNew()", err)
panic(err)
}
@@ -182,6 +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 {
+ logger.LogError("PANIC!!! - MustButtonText()", "gtk.ButtonNewWithLabel()", err)
panic(err)
}
@@ -194,23 +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"
}
- p, err := gdk.PixbufNewFromFileAtScale(imageFilePath, width, height, true)
+ 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(p)
+ image, err := gtk.ImageNewFromPixbuf(pixbuf)
if err != nil {
+ logger.LogError("PANIC!!! - MustImageFromFileWithSize()", "gtk.ImageNewFromPixbuf()", err)
panic(err)
}
@@ -220,36 +236,79 @@ 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 {
+ logger.LogError("PANIC!!! - MustImageFromFile()", "gtk.ImageNewFromFile()", err)
panic(err)
}
return image
}
+func ImageFromUrl(imageUrl string) (*gtk.Image, error) {
+ if imageUrl == "" {
+ logger.Error("ImageFromUrl() - 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()
+ cssProvider, err := gtk.CssProviderNew()
if err != nil {
+ logger.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 {
+ logger.LogError("PANIC!!! - MustCSSProviderFromFile()", "cssProvider.LoadFromPath()", err)
panic(err)
}
- return p
+ return cssProvider
}
func imagePath(imageFileName string) string {
@@ -258,10 +317,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 {
+ logger.LogError("PANIC!!! - MustOverlay()", "gtk.OverlayNew()", err)
panic(err)
}
- return o
+ return overlay
}
diff --git a/utils/logger.go b/utils/logger.go
deleted file mode 100755
index 8dce953..0000000
--- a/utils/logger.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package utils
-
-import (
- "io"
- standardLog "log"
- "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
-}
-
-
-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)
-}
-
-
-func init() {
- log = logrus.New()
- log.AddHook(ContextHook{})
-
- // Start off with the logging level set to debug until we get a chance to read the configuration settings.
- SetLogLevel(logrus.DebugLevel)
-
- 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
- } else {
- log.Infof("logger.init() - logFilePath is: %q", 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
-
- log.Out = io.MultiWriter(os.Stdout, file)
- logrus.SetOutput(log.Out)
- } else {
- log.Errorf("logger.init() - OpenFile() FAILED! err is: %q", err)
- log.Error("Failed to log to file, using default stderr")
- }
- }
-
- Logger = log.WithFields(logrus.Fields{})
-}
-
-func LogError(currentFunctionName, functionNameCalled string, err error) {
- if err != nil {
- Logger.Errorf("%s - %s returned an error: %q", currentFunctionName, functionNameCalled, err)
- } else {
- Logger.Errorf("%s - %s returned an error", currentFunctionName, functionNameCalled)
- }
-}
-
-func LogFatalError(currentFunctionName, functionNameCalled string, err error) {
- if err != nil {
- Logger.Fatalf("%s - %s returned an error: %q", currentFunctionName, functionNameCalled, err)
- } else {
- Logger.Fatalf("%s - %s returned an error", currentFunctionName, functionNameCalled)
- }
-}
diff --git a/utils/string_utils.go b/utils/string_utils.go
index 012559c..f2911a0 100755
--- a/utils/string_utils.go
+++ b/utils/string_utils.go
@@ -1,7 +1,7 @@
-
package utils
import (
+ "encoding/json"
"fmt"
"strings"
)
@@ -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,34 @@ func StrEllipsisLen(name string, length int) string {
return name
}
+
+func TruncateString(str string, maxLength int) string {
+ if maxLength < 3 {
+ maxLength = 3
+ }
+
+ strLen := len(str)
+ if strLen <= maxLength {
+ return str
+ }
+
+ truncateString := str
+ if maxLength > 3 {
+ maxLength -= 3
+ }
+
+ truncateString = str[0:maxLength] + "..."
+
+ 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
+ }
+}
diff --git a/utils/tools.go b/utils/tools.go
index dab1ae5..4166962 100755
--- a/utils/tools.go
+++ b/utils/tools.go
@@ -2,65 +2,96 @@ package utils
import (
"fmt"
- "strings"
"strconv"
+ "strings"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
+ "github.com/Z-Bolt/OctoScreen/logger"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis"
+ "github.com/Z-Bolt/OctoScreen/octoprintApis/dataModels"
)
-var cachedToolheadCount = -1
+var cachedExtruderCount = -1
+var cachedHasSharedNozzle = false
-func GetToolheadCount(client *octoprint.Client) int {
- if cachedToolheadCount != -1 {
- return cachedToolheadCount
+func getCachedPrinterProfileData(client *octoprintApis.Client) {
+ if cachedExtruderCount != -1 {
+ return
}
- connectionResponse, err := (&octoprint.ConnectionRequest{}).Do(client)
+ connectionResponse, err := (&octoprintApis.ConnectionRequest{}).Do(client)
if err != nil {
- LogError("toolhaad.GetToolheadCount()", "Do(ConnectionRequest)", err)
- return 0
+ logger.LogError("Tools.setCachedPrinterProfileData()", "version.Get()", err)
+ return
}
- 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
+ logger.LogError("Tools.setCachedPrinterProfileData()", "Do(PrinterProfilesRequest)", err)
+ return
}
- cachedToolheadCount = printerProfile.Extruder.Count
- if printerProfile.Extruder.SharedNozzle {
- cachedToolheadCount = 1
- } else if cachedToolheadCount > 4 {
- cachedToolheadCount = 4
+ cachedExtruderCount = printerProfile.Extruder.Count
+ if cachedExtruderCount > 4 {
+ cachedExtruderCount = 4
}
+ cachedHasSharedNozzle = printerProfile.Extruder.HasSharedNozzle
+}
+
- // TESTING: uncomment to force all toolheads to display and use for testing
- // cachedToolheadCount = 2
- // cachedToolheadCount = 3
- // cachedToolheadCount = 4
+func GetExtruderCount(client *octoprintApis.Client) int {
+ if cachedExtruderCount == -1 {
+ getCachedPrinterProfileData(client)
+ }
+
+ return cachedExtruderCount
+}
+
+func GetHotendCount(client *octoprintApis.Client) int {
+ if cachedExtruderCount == -1 {
+ getCachedPrinterProfileData(client)
+ }
+
+ 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 == "" {
- 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 ""
}
@@ -72,99 +103,103 @@ func GetDisplayNameForTool(toolName string) string {
}
-func GetToolTarget(client *octoprint.Client, tool string) (float64, error) {
- Logger.Debug("entering Tools.GetToolTarget()")
+func GetToolTarget(client *octoprintApis.Client, tool string) (float64, error) {
+ logger.TraceEnter("Tools.GetToolTarget()")
-
- fullStateRequest, err := (&octoprint.FullStateRequest{
+ 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 := fullStateRequest.Temperature.CurrentTemperatureData[tool]
+ 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 *octoprint.Client, tool string, target float64) error {
- Logger.Debug("entering Tools.SetToolTarget()")
+func SetToolTarget(client *octoprintApis.Client, tool string, target float64) error {
+ logger.TraceEnter("Tools.SetToolTarget()")
if tool == "bed" {
- cmd := &octoprint.BedTargetRequest{Target: target}
-
- Logger.Debug("leaving Tools.SetToolTarget()")
+ cmd := &octoprintApis.BedTargetRequest{Target: target}
+ logger.TraceLeave("Tools.SetToolTarget()")
return cmd.Do(client)
}
- cmd := &octoprint.ToolTargetRequest{Targets: map[string]float64{tool: target}}
-
- Logger.Debug("leaving Tools.SetToolTarget()")
+ cmd := &octoprintApis.ToolTargetRequest{Targets: map[string]float64{tool: target}}
+ logger.TraceLeave("Tools.SetToolTarget()")
return cmd.Do(client)
}
-func GetCurrentTemperatureData(client *octoprint.Client) (map[string]octoprint.TemperatureData, error) {
- Logger.Debug("entering Tools.GetCurrentTemperatureData()")
+func GetCurrentTemperatureData(client *octoprintApis.Client) (map[string]dataModels.TemperatureData, error) {
+ logger.TraceEnter("Tools.GetCurrentTemperatureData()")
- temperatureDataResponse, err := (&octoprint.TemperatureDataRequest{}).Do(client)
+ 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 CurrentHotendTemperatureIsTooLow(client *octoprint.Client, extruderId, action string, parentWindow *gtk.Window) bool {
+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
}
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)
+
+ logger.TraceLeave("Tools.CheckIfHotendTemperatureIsTooLow()")
return true
}
+ logger.TraceLeave("Tools.CheckIfHotendTemperatureIsTooLow()")
return false
}
-
func GetToolheadFileName(hotendIndex, hotendCount int) string {
strImageFileName := ""
if hotendIndex == 1 && hotendCount == 1 {
@@ -176,6 +211,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 {
@@ -187,6 +234,8 @@ func GetHotendFileName(hotendIndex, hotendCount int) string {
return strImageFileName
}
+
+
func GetNozzleFileName(hotendIndex, hotendCount int) string {
strImageFileName := ""
if hotendIndex == 1 && hotendCount == 1 {
@@ -198,6 +247,29 @@ func GetNozzleFileName(hotendIndex, hotendCount int) string {
return strImageFileName
}
-func GetTemperatureDataString(temperatureData octoprint.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 0f92228..05810bf 100755
--- a/utils/ui_utils.go
+++ b/utils/ui_utils.go
@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/gotk3/gotk3/gtk"
- "github.com/mcuadros/go-octoprint"
)
@@ -76,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(
@@ -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 octoprint.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) {
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 0000000..6dcbf21
--- /dev/null
+++ b/vendor/github.com/mcuadros/go-octoprint/FileRequest.go
@@ -0,0 +1,138 @@
+//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
+}
+
+// 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/vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go b/vendor/github.com/mcuadros/go-octoprint/FullStateRequest.go
new file mode 100755
index 0000000..6de286f
--- /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 0000000..e2bebb5
--- /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 0000000..00e4a47
--- /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 0000000..9bb2274
--- /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 0000000..6206a6f
--- /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 0000000..f05a98f
--- /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 0000000..3818a0b
--- /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/client.go b/vendor/github.com/mcuadros/go-octoprint/client.go
index 6d3e259..9e33d8e 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/common.go b/vendor/github.com/mcuadros/go-octoprint/common.go
index 603b9bc..0024c51 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 FileInformation `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"`
+
+// // 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"`
+// }
- 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 {
@@ -272,8 +283,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,62 +292,64 @@ type FilesResponse struct {
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"`
+// 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 {
@@ -395,11 +408,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
diff --git a/vendor/github.com/mcuadros/go-octoprint/connection.go b/vendor/github.com/mcuadros/go-octoprint/connection.go
index 0345ada..809ccbd 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 fa3b789..80664c2 100644..100755
--- a/vendor/github.com/mcuadros/go-octoprint/files.go
+++ b/vendor/github.com/mcuadros/go-octoprint/files.go
@@ -11,65 +11,73 @@ import (
type Location string
const (
- URIFiles = "/api/files"
+ // URIFiles = "/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
-}
+// 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.
@@ -203,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"`
-}
-
-// 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,
- })
-}
+// 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/vendor/github.com/mcuadros/go-octoprint/job.go b/vendor/github.com/mcuadros/go-octoprint/job.go
index d337283..27a093d 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{
+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 f1bb3a4..01d05f0 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"
@@ -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.",
}
@@ -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
+// }
@@ -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 0aaea5b..a327db0 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",
}