Merge branch 'feature/printerdriver' of github.com:Doodle3D/doodle3d-firmware into feature/printerdriver

This commit is contained in:
Wouter R 2013-10-22 20:36:26 +02:00
commit 5c7df6da36
4 changed files with 118 additions and 55 deletions

View File

@ -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 = ''
}

View File

@ -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,23 @@ 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 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)
response:addData('id', argId)

View File

@ -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

View File

@ -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