From c3bb0359bf68ee67ad1a4a1f41467220e8f2a04a Mon Sep 17 00:00:00 2001 From: peteruithoven Date: Tue, 22 Oct 2013 03:30:23 +0200 Subject: [PATCH 1/3] Better error reporting, always using state, making version argument optional --- src/rest/api/api_update.lua | 72 ++++++++++++++++++++++++++----------- src/script/d3d-updater.lua | 61 +++++++++++++++---------------- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/rest/api/api_update.lua b/src/rest/api/api_update.lua index 7ef95a9..4daf1e7 100644 --- a/src/rest/api/api_update.lua +++ b/src/rest/api/api_update.lua @@ -14,27 +14,31 @@ local M = { function M.status(request, response) updater.setLogger(log) updater.setUseCache(false) - local status,msg = updater.getStatus() - if not status then + local success,status,msg = updater.getStatus() + + --response:addData('current_version', status.currentVersion) + response:addData('current_version', updater.formatVersion(status.currentVersion)) + + response:addData('state_code', status.stateCode) + response:addData('state_text', status.stateText) + + if not success then response:setFail(msg) return end local canUpdate = updater.compareVersions(status.newestVersion, status.currentVersion) > 0 - - response:addData('current_version', updater.formatVersion(status.currentVersion)) - response:addData('newest_version', updater.formatVersion(status.newestVersion)) - --response:addData('current_version', status.currentVersion) + --response:addData('newest_version', status.newestVersion) + response:addData('newest_version', updater.formatVersion(status.newestVersion)) response:addData('can_update', canUpdate) - response:addData('state_code', status.stateCode) - response:addData('state_text', status.stateText) + if status.progress then response:addData('progress', status.progress) end if status.imageSize then response:addData('image_size', status.imageSize) end response:setSuccess() end --- requires: version(string) (major.minor.patch) +-- accepts: version(string) (major.minor.patch) -- accepts: clear_gcode(bool, defaults to true) (this is to lower the chance on out-of-memory crashes, but still allows overriding this behaviour) -- accepts: clear_images(bool, defaults to true) (same rationale as with clear_gcode) -- note: call this with a long timeout - downloading may take a while (e.g. ~3.3MB with slow internet...) @@ -45,17 +49,27 @@ function M.download_POST(request, response) if argClearGcode == nil then argClearGcode = true end if argClearImages == nil then argClearImages = true end - if not argVersion then - response:setError("missing version argument") - return - end - updater.setLogger(log) + + updater.setState(updater.STATE.DOWNLOADING,"") + local vEnt, rv, msg - + + if not argVersion then + local success,status,msg = updater.getStatus() + if not success then + updater.setState(updater.STATE.DOWNLOAD_FAILED, msg) + response:setFail(msg) + return + else + argVersion = updater.formatVersion(status.newestVersion) + end + end + if argClearImages then rv,msg = updater.clear() if not rv then + updater.setState(updater.STATE.DOWNLOAD_FAILED, msg) response:setFail(msg) return end @@ -66,6 +80,7 @@ function M.download_POST(request, response) local rv,msg = printer:clearGcode() if not rv then + updater.setState(updater.STATE.DOWNLOAD_FAILED, msg) response:setError(msg) return end @@ -73,15 +88,18 @@ function M.download_POST(request, response) vEnt,msg = updater.findVersion(argVersion) if vEnt == nil then + updater.setState(updater.STATE.DOWNLOAD_FAILED, "error searching version index (" .. msg .. ")") response:setFail("error searching version index (" .. msg .. ")") return elseif vEnt == false then + updater.setState(updater.STATE.DOWNLOAD_FAILED, "no such version") response:setFail("no such version") return end rv,msg = updater.downloadImageFile(vEnt) if not rv then + updater.setState(updater.STATE.DOWNLOAD_FAILED, msg) response:setFail(msg) return end @@ -93,25 +111,39 @@ end function M.install_POST(request, response) local argVersion = request:get("version") updater.setLogger(log) - + + log:info("API:update/install") + updater.setState(updater.STATE.INSTALLING,"") + if not argVersion then - response:setError("missing version argument") - return + local success,status,msg = updater.getStatus() + if not success then + updater.setState(updater.STATE.INSTALL_FAILED, msg) + response:setFail(msg) + return + else + argVersion = updater.formatVersion(status.newestVersion) + end end vEnt,msg = updater.findVersion(argVersion) if vEnt == nil then + updater.setState(updater.STATE.INSTALL_FAILED, "error searching version index (" .. msg .. ")") response:setFail("error searching version index (" .. msg .. ")") return elseif vEnt == false then + updater.setState(updater.STATE.INSTALL_FAILED, "no such version") response:setFail("no such version") return end local rv,msg = updater.flashImageVersion(vEnt) - if not rv then response:setFail("installation failed (" .. msg .. ")") - else response:setSuccess() + if not rv then + updater.setState(updater.STATE.INSTALL_FAILED, "installation failed (" .. msg .. ")") + response:setFail("installation failed (" .. msg .. ")") + else + response:setSuccess() end end diff --git a/src/script/d3d-updater.lua b/src/script/d3d-updater.lua index e804efd..13aa64c 100755 --- a/src/script/d3d-updater.lua +++ b/src/script/d3d-updater.lua @@ -113,23 +113,6 @@ local function getState() return code,msg end --- NOTE: make sure the cache directory exists before calling this function or it will fail. --- NOTE: this function _can_ fail but we don't expect this to happen so the return value is ignored for now -local function setState(code, msg) - local s = code .. '|' .. msg - D("set update state: " .. M.STATE_NAMES[code] .. " ('" .. s .. "')") - local file,msg = io.open(M.CACHE_PATH .. '/' .. M.STATE_FILE, 'w') - - if not file then - E("error: could not open state file for writing (" .. msg .. ")") - return false - end - - file:write(s) - file:close() - return true -end - -- trim whitespace from both ends of string (from http://snippets.luacode.org/?p=snippets/trim_whitespace_from_string_76) local function trim(s) if type(s) ~= 'string' then return s end @@ -267,25 +250,27 @@ function M.getStatus() local unknownVersion = { major = 0, minor = 0, patch = 0 } local result = {} + result.currentVersion = M.getCurrentVersion() + result.stateCode, result.stateText = getState() + result.stateCode = tonumber(result.stateCode) + local verTable,msg = M.getAvailableVersions() if not verTable then D("could not obtain available versions (" .. msg .. ")") -- TODO: set an error state in result to signify we probably do not have internet access? + return false, result, msg end local newest = verTable and verTable[#verTable] - result.currentVersion = M.getCurrentVersion() result.newestVersion = newest and newest.version or unknownVersion - result.stateCode, result.stateText = getState() - result.stateCode = tonumber(result.stateCode) - + if result.stateCode == M.STATE.DOWNLOADING then result.progress = fileSize(M.CACHE_PATH .. '/' .. newest.sysupgradeFilename) if not result.progress then result.progress = 0 end -- in case the file does not exist yet (which yields nil) result.imageSize = newest.sysupgradeFileSize end - return result + return true, result end -- Turns a plain-text version into a table. @@ -454,24 +439,24 @@ function M.downloadImageFile(versionEntry, devType, isFactory) local rv = 0 if doDownload then - setState(M.STATE.DOWNLOADING, "Downloading image (" .. filename .. ")") + M.setState(M.STATE.DOWNLOADING, "Downloading image (" .. filename .. ")") rv = downloadFile(baseUrl .. '/images/' .. filename, M.CACHE_PATH, filename) end if rv == 0 then if M.checkValidImage(versionEntry, devType, isFactory) then - setState(M.STATE.IMAGE_READY, "Image downloaded, ready to install (image name: " .. filename .. ")") + M.setState(M.STATE.IMAGE_READY, "Image downloaded, ready to install (image name: " .. filename .. ")") return true else removeFile(M.CACHE_PATH .. '/' .. filename) local ws = "Image download failed (invalid image)" - setState(M.STATE_DOWNLOAD_FAILED, ws) + M.setState(M.STATE.DOWNLOAD_FAILED, ws) return nil,ws end else local ws = wgetStatusToString(rv) removeFile(M.CACHE_PATH .. '/' .. filename) - setState(M.STATE.DOWNLOAD_FAILED, "Image download failed (wget error: " .. ws .. ")") + M.setState(M.STATE.DOWNLOAD_FAILED, "Image download failed (wget error: " .. ws .. ")") return nil,ws end end @@ -480,6 +465,7 @@ end -- noRetain, devType and isFactory are optional -- returns true or nil + wget return value function M.flashImageVersion(versionEntry, noRetain, devType, isFactory) + log:info("flashImageVersion") local imgName = M.constructImageFilename(versionEntry.version, devType, isFactory) local cmd = noRetain and 'sysupgrade -n ' or 'sysupgrade ' cmd = cmd .. M.CACHE_PATH .. '/' .. imgName @@ -491,15 +477,15 @@ function M.flashImageVersion(versionEntry, noRetain, devType, isFactory) return nil,"no valid image for requested version present" end - setState(M.STATE.INSTALLING, "Installing new image (" .. imgName .. ")") -- yes this is rather pointless + M.setState(M.STATE.INSTALLING, "Installing new image (" .. imgName .. ")") -- yes this is rather pointless local rv = runCommand(cmd) -- if everything goes to plan, this will not return if rv == 0 then - setState(M.STATE.INSTALLED, "Image installed") + M.setState(M.STATE.INSTALLED, "Image installed") else -- NOTE: if cmdrv == 127, this means the command was not found local cmdrv,sysrv = splitExitStatus(rv) - setState(M.STATE.INSTALL_FAILED, "Image installation failed (sysupgrade returned " .. cmdrv .. ", execution status: " .. sysrv .. ")") + M.setState(M.STATE.INSTALL_FAILED, "Image installation failed (sysupgrade returned " .. cmdrv .. ", execution status: " .. sysrv .. ")") end return (rv == 0) and true or nil,rv @@ -511,12 +497,27 @@ function M.clear() if not ccRv then return nil,ccMsg end D("Removing " .. M.CACHE_PATH .. "/doodle3d-wifibox-*.bin") - setState(M.STATE.NONE, "") + M.setState(M.STATE.NONE, "") local rv = os.execute('rm -f ' .. M.CACHE_PATH .. '/doodle3d-wifibox-*.bin') return (rv == 0) and true or nil,"could not remove image files" end +-- NOTE: make sure the cache directory exists before calling this function or it will fail. +-- NOTE: this function _can_ fail but we don't expect this to happen so the return value is ignored for now +function M.setState(code, msg) + local s = code .. '|' .. msg + D("set update state: " .. M.STATE_NAMES[code] .. " ('" .. s .. "')") + local file,msg = io.open(M.CACHE_PATH .. '/' .. M.STATE_FILE, 'w') + if not file then + E("error: could not open state file for writing (" .. msg .. ")") + return false + end + + file:write(s) + file:close() + return true +end From 8ab87312b3e30f09b545d09986a31a897214a5be Mon Sep 17 00:00:00 2001 From: peteruithoven Date: Tue, 22 Oct 2013 13:51:02 +0200 Subject: [PATCH 2/3] Replacing variables in endcode on API:printer/stop --- src/rest/api/api_printer.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rest/api/api_printer.lua b/src/rest/api/api_printer.lua index b4d085f..bc90205 100644 --- a/src/rest/api/api_printer.lua +++ b/src/rest/api/api_printer.lua @@ -106,6 +106,8 @@ end function M.stop_POST(request, response) + log:info("API:printer/stop") + if not accessManager.hasControl(request.remoteAddress) then response:setFail("No control access") return @@ -114,8 +116,14 @@ function M.stop_POST(request, response) local argId = request:get("id") local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end - - local endGcode = settings.get('printer.endgcode') + + -- replacing {printingTemp} and {preheatTemp} in endgcode + local printingTemperature = settings.get('printer.temperature') + local preheatTemperature = settings.get('printer.heatup.temperature') + local endGcode = settings.get('printer.endgcode') + endGcode = string.gsub(endGcode,"{printingTemp}",printingTemperature) + endGcode = string.gsub(endGcode,"{preheatTemp}",preheatTemperature) + local rv,msg = printer:stopPrint(endGcode) response:addData('id', argId) From 78a71ca625120b3082377bbf5b35ef39fa6d99c1 Mon Sep 17 00:00:00 2001 From: peteruithoven Date: Tue, 22 Oct 2013 16:00:37 +0200 Subject: [PATCH 3/3] Bed temperatures --- src/conf_defaults.lua | 19 ++++++++++++++++--- src/rest/api/api_printer.lua | 9 +++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/conf_defaults.lua b/src/conf_defaults.lua index 4b32cd9..c7141b6 100644 --- a/src/conf_defaults.lua +++ b/src/conf_defaults.lua @@ -98,7 +98,14 @@ M.printer_baudrate = { M.printer_temperature = { default = 230, type = 'int', - description = '3D printer temperature', + description = 'printing temperature', + min = 0 +} + +M.printer_bed_temperature = { + default = 70, + type = 'int', + description = 'printing bed temperature', min = 0 } @@ -161,6 +168,12 @@ M.printer_heatup_temperature = { description = '' } +M.printer_heatup_bed_temperature = { + default = 70, + type = 'int', + description = '' +} + M.printer_retraction_enabled = { default = true, type = 'bool', @@ -195,13 +208,13 @@ M.printer_enableTraveling = { } M.printer_startgcode = { - default = ';Generated with Doodle3D\nM109 S{printingTemp} ;set target temperature \nG21 ;metric values\nG91 ;relative positioning\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG92 E0 ;zero the extruded length again\nG1 F9000\nG90 ;absolute positioning\nM117 Printing Doodle... ;display message (20 characters to clear whole screen)', + default = ';Generated with Doodle3D\nM109 S{printingTemp} ;set target temperature \n;M190 S{printingBedTemp} ;set target bed temperature\nG21 ;metric values\nG91 ;relative positioning\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG92 E0 ;zero the extruded length again\nG1 F9000\nG90 ;absolute positioning\nM117 Printing Doodle... ;display message (20 characters to clear whole screen)', type = 'string', description = '' } M.printer_endgcode = { - default = 'M107 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;disable axes / steppers\nG90 ;absolute positioning\nM104 {preheatTemp}\nM117 Done ;display message (20 characters to clear whole screen)', + default = 'M107 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;disable axes / steppers\nG90 ;absolute positioning\nM104 S{preheatTemp}\n;M140 S{preheatBedTemp}\nM117 Done ;display message (20 characters to clear whole screen)', type = 'string', description = '' } diff --git a/src/rest/api/api_printer.lua b/src/rest/api/api_printer.lua index bc90205..4a7bc02 100644 --- a/src/rest/api/api_printer.lua +++ b/src/rest/api/api_printer.lua @@ -119,10 +119,19 @@ function M.stop_POST(request, response) -- replacing {printingTemp} and {preheatTemp} in endgcode local printingTemperature = settings.get('printer.temperature') + local printingBedTemperature = settings.get('printer.bed.temperature') local preheatTemperature = settings.get('printer.heatup.temperature') + local preheatBedTemperature = settings.get('printer.heatup.bed.temperature') local endGcode = settings.get('printer.endgcode') + + --log:info(" printingBedTemperature: "..utils.dump(printingBedTemperature)) + --log:info(" preheatBedTemperature: "..utils.dump(preheatBedTemperature)) + --log:info(" endGcode : "..utils.dump(endGcode)) endGcode = string.gsub(endGcode,"{printingTemp}",printingTemperature) + endGcode = string.gsub(endGcode,"{printingBedTemp}",printingBedTemperature) endGcode = string.gsub(endGcode,"{preheatTemp}",preheatTemperature) + endGcode = string.gsub(endGcode,"{preheatBedTemp}",preheatBedTemperature) + --log:info(" >endGcode : "..utils.dump(endGcode)) local rv,msg = printer:stopPrint(endGcode)