diff --git a/src/main.lua b/src/main.lua index 3b33c2a..0c1a78e 100644 --- a/src/main.lua +++ b/src/main.lua @@ -201,7 +201,7 @@ local function main(environment) if err ~= nil then log:error(err) end response:send() - response:executePostResponseQueue() + response:executePostResponseQueue() else log:info("Nothing to do...bye.\n") end diff --git a/src/network/netconfig.lua b/src/network/netconfig.lua index f7fb184..821bc37 100644 --- a/src/network/netconfig.lua +++ b/src/network/netconfig.lua @@ -3,6 +3,7 @@ local log = require('util.logger') local settings = require('util.settings') local wifi = require('network.wlanconfig') local uci = require('uci').cursor() +local signin = require('network.signin') local M = {} local reconf = {} @@ -13,7 +14,12 @@ M.WWW_CAPTIVE_PATH = '/usr/share/lua/wifibox/www' M.WWW_CAPTIVE_INDICATOR = '/www/.wifibox-inplace' M.WWW_RENAME_NAME = '/www-regular' - +M.CONNECTING_FAILED = -1 +M.NOT_CONNECTED = 0 +M.CONNECTING = 1 +M.CONNECTED = 2 +M.CREATING = 3 +M.CREATED = 4 local function reloadBit(dlist, itemname) if dlist[itemname] == nil then dlist[itemname] = '' end @@ -250,11 +256,16 @@ end -- @tparam string ssid The SSID to use for the access point. -- @return True on success or nil+msg on error. function M.setupAccessPoint(ssid) + + M.setStatus(M.CREATING,"Creating access point..."); + M.switchConfiguration{apnet="add_noreload"} wifi.activateConfig(ssid) -- NOTE: dnsmasq must be reloaded after network or it will be unable to serve IP addresses M.switchConfiguration{ wifiiface="add", network="reload", staticaddr="add", dhcppool="add_noreload", wwwredir="add", dnsredir="add" } M.switchConfiguration{dhcp="reload"} + + M.setStatus(M.CREATED,"Access point created"); return true end @@ -268,6 +279,9 @@ end -- @return True on success or nil+msg on error. function M.associateSsid(ssid, passphrase, recreate) log:info("netconfig:associateSsid: "..(ssid or "")..", "..(passphrase or "")..", "..(recreate or "")) + + M.setStatus(M.CONNECTING,"Connecting..."); + -- see if previously configured network for given ssid exists local cfg = nil for _, net in ipairs(wifi.getConfigs()) do @@ -284,7 +298,9 @@ function M.associateSsid(ssid, passphrase, recreate) wifi.createConfigFromScanInfo(scanResult, passphrase) else --check for error - return nil,"no wireless network with requested SSID is available" + local msg = "Wireless network "..ssid.." is not available" + M.setStatus(M.CONNECTING_FAILED,msg); + return nil,msg end end @@ -297,10 +313,59 @@ function M.associateSsid(ssid, passphrase, recreate) -- check if we are actually associated local status = wifi.getDeviceState() if not status.ssid or status.ssid ~= ssid then - return nil,"could not associate with network (incorrect passphrase?)" + local msg = "Could not associate with network (incorrect password?)" + M.setStatus(M.CONNECTING_FAILED,msg); + return nil,msg + end + + M.setStatus(M.CONNECTED,"Connected"); + + -- signin to connect.doodle3d.com + local success, output = signin.signin() + if success then + log:info("API:Network:signed in") + else + log:info("API:Network:Signing in failed") end return true end +--- Disassociate wlan device as client from all SSID's. +-- Note: this function might belong in the wlanconfig module but that would introduce +-- a circular dependency, easiest solution is to place the function here. +-- @return True on success or nil+msg on error. +function M.disassociate() + + M.setStatus(M.NOT_CONNECTED,"Not connected"); + + wifi.activateConfig() + return wifi.restart() +end + +function M.getStatus() + log:info("getStatus") + local file, error = io.open('/tmp/networkstatus.txt','r') + if file == nil then + --log:error("Util:Access:Can't read controller file. Error: "..error) + return "","" + else + local status = file:read('*a') + --log:info(" status: "..utils.dump(status)) + file:close() + local parts = {} + local code, msg = string.match(status, "([^|]+)|+(.*)") + --log:info(" code: "..utils.dump(code)) + --log:info(" msg: "..utils.dump(msg)) + return code,msg + end +end + +function M.setStatus(code,msg) + log:info("setStatus: "..code.." | "..msg) + local file = io.open('/tmp/networkstatus.txt','w') + file:write(code.."|"..msg) + file:flush() + file:close() +end return M diff --git a/src/rest/api/api_info.lua b/src/rest/api/api_info.lua index fdc7e71..26dc22f 100644 --- a/src/rest/api/api_info.lua +++ b/src/rest/api/api_info.lua @@ -1,4 +1,10 @@ local lfs = require('lfs') +local log = require('util.logger') +local utils = require('util.utils') +local accessManager = require('util.access') +local printDriver = require('print3d') +local printerUtils = require('util.printer') +--local printerAPI = require('rest.api.api_printer') local TMP_DIR = '/tmp' local LOG_COLLECT_DIRNAME = 'wifibox-logs' @@ -15,7 +21,6 @@ local function redirectedExecute(cmd) return os.execute(cmd .. " > /dev/null 2>&1") end - local M = { isApi = true } @@ -90,4 +95,90 @@ function M.logfiles(request, response) local rv,sig,code = redirectedExecute('rm ' .. LOG_COLLECT_ARCHIVE_FILE) end +function M.access(request, response) + --log:info(" remoteAddress: |"..utils.dump(request.remoteAddress).."|"); + --log:info(" controller: |"..utils.dump(accessManager.getController()).."|"); + + -- when there is a controller we check if the printer is idle, + -- if so, it should be done printing and we can clear the controller + if accessManager.getController() ~= "" then + local argId = request:get("id") + local printer,msg = printerUtils.createPrinterOrFail(argId, response) + local rv,msg = printer:getState() + if rv then + response:setSuccess() + if(state == "idle") then -- TODO: define in constants somewhere + accessManager.setController("") -- clear controller + end + else + response:setError(msg) + return + end + end + + local hasControl = accessManager.hasControl(request.remoteAddress) + response:setSuccess() + response:addData('hasControl', hasControl) + + return +end + +function M.status(request, response) + --[[ + local argId = request:get("id") + local printer,msg = printerUtils.createPrinterOrFail(argId, response) + if not printer then return end + + response:addData('id', argId) + + -- Temperature + local temperatures,msg = printer:getTemperatures() + if temperatures then + response:setSuccess() + response:addData('hotend', temperatures.hotend) + response:addData('hotend_target', temperatures.hotend_target) + response:addData('bed', temperatures.bed) + response:addData('bed_target', temperatures.bed_target) + else + response:setError(msg) + return + end + --TODO: reuse printer/temperature api + + -- Progress + -- NOTE: despite their names, `currentLine` is still the error indicator and `numLines` the message in such case. + local currentLine,numLines = printer:getProgress() + if currentLine then + response:setSuccess() + response:addData('current_line', currentLine) + response:addData('num_lines', numLines) + else + response:setError(numLines) + return + end + --TODO: reuse printer/progress api + + -- State + local rv,msg = printer:getState() + if rv then + response:setSuccess() + response:addData('state', rv) + else + response:setError(msg) + return + end + ]]--- + ----TODO: reuse printer/state api + + --printerAPI.temperature(request, response) + --printerAPI.progress(request, response) + --printerAPI.state(request, response) + + -- access + M.access(request, response) + + response:addData('v', 8) + +end + return M diff --git a/src/rest/api/api_network.lua b/src/rest/api/api_network.lua index 4c43935..27ed4d1 100644 --- a/src/rest/api/api_network.lua +++ b/src/rest/api/api_network.lua @@ -78,11 +78,10 @@ function M.status(request, response) local withRaw = utils.toboolean(request:get("with_raw")) local ds = wifi.getDeviceState() - if ds.ssid == nil then - response:setFail("Not connected") - else - response:setSuccess() - end + local statusCode, statusMessage = netconf.getStatus() + response:addData("status",statusCode) + response:addData("statusMessage",statusMessage) + response:setSuccess(statusMessage) response:addData("ssid", ds.ssid or "") response:addData("bssid", ds.bssid or "") @@ -94,6 +93,9 @@ function M.status(request, response) response:addData("txpower", ds.txpower) response:addData("signal", ds.signal) response:addData("noise", ds.noise) + + + if withRaw then response:addData("_raw", utils.dump(ds)) end local localip = wifi.getLocalIP() @@ -102,10 +104,6 @@ end --requires ssid(string), accepts phrase(string), recreate(bool) function M.associate_POST(request, response) - local utils = require('util.utils') - local log = require('util.logger') - log:info("API:Network:associate") - local argSsid = request:get("ssid") local argPhrase = request:get("phrase") local argRecreate = request:get("recreate") @@ -114,38 +112,22 @@ function M.associate_POST(request, response) response:setError("missing ssid argument") return end - - local associate = function() - local rv,msg = netconf.associateSsid(argSsid, argPhrase, argRecreate) - end - response:addPostResponseFunction(associate) - + response:setSuccess("wlan is trying to associate") - --[[local helloA = function() - local log = require('util.logger') - log:info("HELLO A") - end - response:addPostResponseFunction(helloA) - - local helloB = function() - local log = require('util.logger') - log:info("HELLO B") - end - response:addPostResponseFunction(helloB)]]-- - - --[[response:addData("ssid", argSsid) + local rv,msg = netconf.associateSsid(argSsid, argPhrase, argRecreate) if rv then - response:setSuccess("wlan associated") - else - response:setFail(msg) - end]]-- - response:setSuccess("wlan is trying to associate") + log:info("associated to wifi: "..utils.dump(argSsid)) + else + log:info("failed to associate to wifi: "..utils.dump(argSsid).." ("..utils.dump(msg)..")") + end + end function M.disassociate_POST(request, response) - wifi.activateConfig() - local rv = wifi.restart() + + local rv = netconf.disassociate() + response:setSuccess("all wireless networks deactivated") response:addData("wifi_restart_result", rv) end diff --git a/src/rest/api/api_printer.lua b/src/rest/api/api_printer.lua index d4f02ed..77ebc44 100644 --- a/src/rest/api/api_printer.lua +++ b/src/rest/api/api_printer.lua @@ -3,6 +3,8 @@ local log = require('util.logger') local utils = require('util.utils') local settings = require('util.settings') local printDriver = require('print3d') +local printerUtils = require('util.printer') +local accessManager = require('util.access') local M = { isApi = true @@ -15,27 +17,6 @@ local PROGRESS_FILE = 'progress2.out' local COMMAND_FILE = 'command.in' local GCODE_TMP_FILE = 'combined.gc' - ---returns a printer instance or nil (and sets error state on response in the latter case) -local function createPrinterOrFail(deviceId, response) - local msg,printer = nil, nil - - if deviceId and deviceId ~= "" then - printer,msg = printDriver.getPrinter(deviceId) - else - msg = "missing device ID" - end - - if not printer then - response:setError("could not open printer driver (" .. msg .. ")") - response:addData('id', deviceId) - return nil - end - - return printer -end - - function M._global(request, response) -- TODO: list all printers (based on /dev/ttyACM* and /dev/ttyUSB*) response:setSuccess() @@ -44,7 +25,7 @@ end --requires id(string) function M.temperature(request, response) local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end local temperatures,msg = printer:getTemperatures() @@ -64,7 +45,7 @@ end --requires id(string) function M.progress(request, response) local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end -- NOTE: despite their names, `currentLine` is still the error indicator and `numLines` the message in such case. @@ -84,7 +65,7 @@ end --requires id(string) function M.busy(request, response) local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end local rv,msg = printer:getState() @@ -101,7 +82,7 @@ end --requires id(string) function M.state(request, response) local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end local rv,msg = printer:getState() @@ -115,10 +96,18 @@ function M.state(request, response) end end + + --requires id(string) function M.heatup_POST(request, response) + + if not accessManager.hasControl(request.remoteAddress) then + response:setFail("No control access") + return + end + local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end local temperature = settings.get('printer.heatup.temperature') @@ -132,8 +121,14 @@ end --requires id(string) function M.stop_POST(request, response) + + if not accessManager.hasControl(request.remoteAddress) then + response:setFail("No control access") + return + end + local argId = request:get("id") - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end local endGcode = settings.get('printer.endgcode') @@ -149,12 +144,28 @@ end --accepts: first(bool) (chunks will be concatenated but output file will be cleared first if this argument is true) --accepts: last(bool) (chunks will be concatenated and only when this argument is true will printing be started) function M.print_POST(request, response) + + local controllerIP = accessManager.getController() + local hasControl = false + if controllerIP == "" then + accessManager.setController(request.remoteAddress) + hasControl = true + elseif controllerIP == request.remoteAddress then + hasControl = true + end + + log:info(" hasControl: "..utils.dump(hasControl)) + if not hasControl then + response:setFail("No control access") + return + end + local argId = request:get("id") local argGcode = request:get("gcode") local argIsFirst = utils.toboolean(request:get("first")) local argIsLast = utils.toboolean(request:get("last")) - local printer,msg = createPrinterOrFail(argId, response) + local printer,msg = printerUtils.createPrinterOrFail(argId, response) if not printer then return end response:addData('id', argId) diff --git a/src/rest/request.lua b/src/rest/request.lua index 1d610b2..34edb94 100644 --- a/src/rest/request.lua +++ b/src/rest/request.lua @@ -3,6 +3,7 @@ local urlcode = require('util.urlcode') local confDefaults = require('conf_defaults') local s = require('util.settings') local ResponseClass = require('rest.response') +local log = require('util.logger') local M = {} M.__index = M @@ -165,6 +166,7 @@ function M.new(environment, postData, debugEnabled) self.remoteHost = environment['REMOTE_HOST'] self.remotePort = environment['REMOTE_PORT'] self.userAgent = environment['HTTP_USER_AGENT'] + self.remoteAddress = environment['REMOTE_ADDR'] else self.requestMethod = 'CMDLINE' end diff --git a/src/util/access.lua b/src/util/access.lua new file mode 100644 index 0000000..44811ce --- /dev/null +++ b/src/util/access.lua @@ -0,0 +1,30 @@ +local log = require('util.logger') +local utils = require('util.utils') + +local M = {} + +function M.hasControl(ip) + local controllerIP = M.getController() + return (controllerIP == "" or (controllerIP ~= "" and controllerIP == ip)) +end + +function M.getController() + local file, error = io.open('/tmp/controller.txt','r') + if file == nil then + --log:error("Util:Access:Can't read controller file. Error: "..error) + return "" + else + controllerIP = file:read('*a') + file:close() + return controllerIP + end +end + +function M.setController(ip) + local file = io.open('/tmp/controller.txt','w') + file:write(ip) + file:flush() + file:close() +end + +return M \ No newline at end of file diff --git a/src/util/logger.lua b/src/util/logger.lua index 562ce39..00c940f 100644 --- a/src/util/logger.lua +++ b/src/util/logger.lua @@ -8,7 +8,6 @@ local utils = require('util.utils') local M = {} - local logLevel, logVerbose, logStream --- Available log levels. diff --git a/src/util/printer.lua b/src/util/printer.lua index 7242460..0b3ce67 100644 --- a/src/util/printer.lua +++ b/src/util/printer.lua @@ -1,3 +1,7 @@ +local log = require('util.logger') +local utils = require('util.utils') +local printDriver = require('print3d') + local SUPPORTED_PRINTERS = { rigidbot = "Rigidbot", ultimaker = "Ultimaker", @@ -46,4 +50,27 @@ function M.supportedBaudRates() return SUPPORTED_BAUDRATES end + + +--returns a printer instance or nil (and sets error state on response in the latter case) +function M.createPrinterOrFail(deviceId, response) + + log:info("API:printer:createPrinterOrFail: "..utils.dump(deviceId)) + local msg,printer = nil, nil + + if deviceId == nil or deviceId == "" then + printer,msg = printDriver.getPrinter() + else + printer,msg = printDriver.getPrinter(deviceId) + end + + if not printer then + response:setError("could not open printer driver (" .. msg .. ")") + response:addData('id', deviceId) + return nil + end + + return printer +end + return M