mirror of
https://github.com/Doodle3D/doodle3d-firmware.git
synced 2024-12-22 19:13:49 +01:00
Better error reporting, always using state, making version argument optional
This commit is contained in:
parent
d069dafb5c
commit
c3bb0359bf
@ -14,27 +14,31 @@ local M = {
|
|||||||
function M.status(request, response)
|
function M.status(request, response)
|
||||||
updater.setLogger(log)
|
updater.setLogger(log)
|
||||||
updater.setUseCache(false)
|
updater.setUseCache(false)
|
||||||
local status,msg = updater.getStatus()
|
local success,status,msg = updater.getStatus()
|
||||||
if not status then
|
|
||||||
|
--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)
|
response:setFail(msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local canUpdate = updater.compareVersions(status.newestVersion, status.currentVersion) > 0
|
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', status.newestVersion)
|
||||||
|
response:addData('newest_version', updater.formatVersion(status.newestVersion))
|
||||||
response:addData('can_update', canUpdate)
|
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.progress then response:addData('progress', status.progress) end
|
||||||
if status.imageSize then response:addData('image_size', status.imageSize) end
|
if status.imageSize then response:addData('image_size', status.imageSize) end
|
||||||
response:setSuccess()
|
response:setSuccess()
|
||||||
end
|
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_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)
|
-- 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...)
|
-- 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 argClearGcode == nil then argClearGcode = true end
|
||||||
if argClearImages == nil then argClearImages = true end
|
if argClearImages == nil then argClearImages = true end
|
||||||
|
|
||||||
if not argVersion then
|
|
||||||
response:setError("missing version argument")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
updater.setLogger(log)
|
updater.setLogger(log)
|
||||||
|
|
||||||
|
updater.setState(updater.STATE.DOWNLOADING,"")
|
||||||
|
|
||||||
local vEnt, rv, msg
|
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
|
if argClearImages then
|
||||||
rv,msg = updater.clear()
|
rv,msg = updater.clear()
|
||||||
if not rv then
|
if not rv then
|
||||||
|
updater.setState(updater.STATE.DOWNLOAD_FAILED, msg)
|
||||||
response:setFail(msg)
|
response:setFail(msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -66,6 +80,7 @@ function M.download_POST(request, response)
|
|||||||
local rv,msg = printer:clearGcode()
|
local rv,msg = printer:clearGcode()
|
||||||
|
|
||||||
if not rv then
|
if not rv then
|
||||||
|
updater.setState(updater.STATE.DOWNLOAD_FAILED, msg)
|
||||||
response:setError(msg)
|
response:setError(msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -73,15 +88,18 @@ function M.download_POST(request, response)
|
|||||||
|
|
||||||
vEnt,msg = updater.findVersion(argVersion)
|
vEnt,msg = updater.findVersion(argVersion)
|
||||||
if vEnt == nil then
|
if vEnt == nil then
|
||||||
|
updater.setState(updater.STATE.DOWNLOAD_FAILED, "error searching version index (" .. msg .. ")")
|
||||||
response:setFail("error searching version index (" .. msg .. ")")
|
response:setFail("error searching version index (" .. msg .. ")")
|
||||||
return
|
return
|
||||||
elseif vEnt == false then
|
elseif vEnt == false then
|
||||||
|
updater.setState(updater.STATE.DOWNLOAD_FAILED, "no such version")
|
||||||
response:setFail("no such version")
|
response:setFail("no such version")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
rv,msg = updater.downloadImageFile(vEnt)
|
rv,msg = updater.downloadImageFile(vEnt)
|
||||||
if not rv then
|
if not rv then
|
||||||
|
updater.setState(updater.STATE.DOWNLOAD_FAILED, msg)
|
||||||
response:setFail(msg)
|
response:setFail(msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -94,24 +112,38 @@ function M.install_POST(request, response)
|
|||||||
local argVersion = request:get("version")
|
local argVersion = request:get("version")
|
||||||
updater.setLogger(log)
|
updater.setLogger(log)
|
||||||
|
|
||||||
|
log:info("API:update/install")
|
||||||
|
updater.setState(updater.STATE.INSTALLING,"")
|
||||||
|
|
||||||
if not argVersion then
|
if not argVersion then
|
||||||
response:setError("missing version argument")
|
local success,status,msg = updater.getStatus()
|
||||||
|
if not success then
|
||||||
|
updater.setState(updater.STATE.INSTALL_FAILED, msg)
|
||||||
|
response:setFail(msg)
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
argVersion = updater.formatVersion(status.newestVersion)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
vEnt,msg = updater.findVersion(argVersion)
|
vEnt,msg = updater.findVersion(argVersion)
|
||||||
if vEnt == nil then
|
if vEnt == nil then
|
||||||
|
updater.setState(updater.STATE.INSTALL_FAILED, "error searching version index (" .. msg .. ")")
|
||||||
response:setFail("error searching version index (" .. msg .. ")")
|
response:setFail("error searching version index (" .. msg .. ")")
|
||||||
return
|
return
|
||||||
elseif vEnt == false then
|
elseif vEnt == false then
|
||||||
|
updater.setState(updater.STATE.INSTALL_FAILED, "no such version")
|
||||||
response:setFail("no such version")
|
response:setFail("no such version")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local rv,msg = updater.flashImageVersion(vEnt)
|
local rv,msg = updater.flashImageVersion(vEnt)
|
||||||
|
|
||||||
if not rv then response:setFail("installation failed (" .. msg .. ")")
|
if not rv then
|
||||||
else response:setSuccess()
|
updater.setState(updater.STATE.INSTALL_FAILED, "installation failed (" .. msg .. ")")
|
||||||
|
response:setFail("installation failed (" .. msg .. ")")
|
||||||
|
else
|
||||||
|
response:setSuccess()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,23 +113,6 @@ local function getState()
|
|||||||
return code,msg
|
return code,msg
|
||||||
end
|
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)
|
-- trim whitespace from both ends of string (from http://snippets.luacode.org/?p=snippets/trim_whitespace_from_string_76)
|
||||||
local function trim(s)
|
local function trim(s)
|
||||||
if type(s) ~= 'string' then return s end
|
if type(s) ~= 'string' then return s end
|
||||||
@ -267,17 +250,19 @@ function M.getStatus()
|
|||||||
local unknownVersion = { major = 0, minor = 0, patch = 0 }
|
local unknownVersion = { major = 0, minor = 0, patch = 0 }
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
|
result.currentVersion = M.getCurrentVersion()
|
||||||
|
result.stateCode, result.stateText = getState()
|
||||||
|
result.stateCode = tonumber(result.stateCode)
|
||||||
|
|
||||||
local verTable,msg = M.getAvailableVersions()
|
local verTable,msg = M.getAvailableVersions()
|
||||||
if not verTable then
|
if not verTable then
|
||||||
D("could not obtain available versions (" .. msg .. ")")
|
D("could not obtain available versions (" .. msg .. ")")
|
||||||
-- TODO: set an error state in result to signify we probably do not have internet access?
|
-- TODO: set an error state in result to signify we probably do not have internet access?
|
||||||
|
return false, result, msg
|
||||||
end
|
end
|
||||||
|
|
||||||
local newest = verTable and verTable[#verTable]
|
local newest = verTable and verTable[#verTable]
|
||||||
result.currentVersion = M.getCurrentVersion()
|
|
||||||
result.newestVersion = newest and newest.version or unknownVersion
|
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
|
if result.stateCode == M.STATE.DOWNLOADING then
|
||||||
result.progress = fileSize(M.CACHE_PATH .. '/' .. newest.sysupgradeFilename)
|
result.progress = fileSize(M.CACHE_PATH .. '/' .. newest.sysupgradeFilename)
|
||||||
@ -285,7 +270,7 @@ function M.getStatus()
|
|||||||
result.imageSize = newest.sysupgradeFileSize
|
result.imageSize = newest.sysupgradeFileSize
|
||||||
end
|
end
|
||||||
|
|
||||||
return result
|
return true, result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turns a plain-text version into a table.
|
-- Turns a plain-text version into a table.
|
||||||
@ -454,24 +439,24 @@ function M.downloadImageFile(versionEntry, devType, isFactory)
|
|||||||
|
|
||||||
local rv = 0
|
local rv = 0
|
||||||
if doDownload then
|
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)
|
rv = downloadFile(baseUrl .. '/images/' .. filename, M.CACHE_PATH, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
if rv == 0 then
|
if rv == 0 then
|
||||||
if M.checkValidImage(versionEntry, devType, isFactory) 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
|
return true
|
||||||
else
|
else
|
||||||
removeFile(M.CACHE_PATH .. '/' .. filename)
|
removeFile(M.CACHE_PATH .. '/' .. filename)
|
||||||
local ws = "Image download failed (invalid image)"
|
local ws = "Image download failed (invalid image)"
|
||||||
setState(M.STATE_DOWNLOAD_FAILED, ws)
|
M.setState(M.STATE.DOWNLOAD_FAILED, ws)
|
||||||
return nil,ws
|
return nil,ws
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local ws = wgetStatusToString(rv)
|
local ws = wgetStatusToString(rv)
|
||||||
removeFile(M.CACHE_PATH .. '/' .. filename)
|
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
|
return nil,ws
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -480,6 +465,7 @@ end
|
|||||||
-- noRetain, devType and isFactory are optional
|
-- noRetain, devType and isFactory are optional
|
||||||
-- returns true or nil + wget return value
|
-- returns true or nil + wget return value
|
||||||
function M.flashImageVersion(versionEntry, noRetain, devType, isFactory)
|
function M.flashImageVersion(versionEntry, noRetain, devType, isFactory)
|
||||||
|
log:info("flashImageVersion")
|
||||||
local imgName = M.constructImageFilename(versionEntry.version, devType, isFactory)
|
local imgName = M.constructImageFilename(versionEntry.version, devType, isFactory)
|
||||||
local cmd = noRetain and 'sysupgrade -n ' or 'sysupgrade '
|
local cmd = noRetain and 'sysupgrade -n ' or 'sysupgrade '
|
||||||
cmd = cmd .. M.CACHE_PATH .. '/' .. imgName
|
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"
|
return nil,"no valid image for requested version present"
|
||||||
end
|
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
|
local rv = runCommand(cmd) -- if everything goes to plan, this will not return
|
||||||
|
|
||||||
if rv == 0 then
|
if rv == 0 then
|
||||||
setState(M.STATE.INSTALLED, "Image installed")
|
M.setState(M.STATE.INSTALLED, "Image installed")
|
||||||
else
|
else
|
||||||
-- NOTE: if cmdrv == 127, this means the command was not found
|
-- NOTE: if cmdrv == 127, this means the command was not found
|
||||||
local cmdrv,sysrv = splitExitStatus(rv)
|
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
|
end
|
||||||
|
|
||||||
return (rv == 0) and true or nil,rv
|
return (rv == 0) and true or nil,rv
|
||||||
@ -511,12 +497,27 @@ function M.clear()
|
|||||||
if not ccRv then return nil,ccMsg end
|
if not ccRv then return nil,ccMsg end
|
||||||
|
|
||||||
D("Removing " .. M.CACHE_PATH .. "/doodle3d-wifibox-*.bin")
|
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')
|
local rv = os.execute('rm -f ' .. M.CACHE_PATH .. '/doodle3d-wifibox-*.bin')
|
||||||
return (rv == 0) and true or nil,"could not remove image files"
|
return (rv == 0) and true or nil,"could not remove image files"
|
||||||
end
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user