mirror of
https://github.com/Doodle3D/doodle3d-firmware.git
synced 2024-12-22 11:03:48 +01:00
Documentation.
Untrack TODO.md.
This commit is contained in:
parent
6c15b2c220
commit
48b9a4a8e1
180
TODO.md
180
TODO.md
@ -1,180 +0,0 @@
|
|||||||
## te doen voor werkend prototype (beta testers)
|
|
||||||
- (testen) server logging
|
|
||||||
- (testen/verder implementeren) stopknop
|
|
||||||
- volgorde chunks (en vaker voorkomen?): elke chunk naar los bestand en op het laatst samenvoegen
|
|
||||||
- (client) autopreheat wanneer er een printer aanwezig is
|
|
||||||
- (fw) temp gcode pad veranderen naar device-specifiek (i.e. /tmp/UltiFi/ttyACM?/combined.gc)
|
|
||||||
- (fw) bij (her)initialisatie printer altijd alle state weggooien (i.e. /dev/UtliFi/ttyACM?)
|
|
||||||
- client feedback
|
|
||||||
* voor ontwikkeling: debugoverlay
|
|
||||||
* vaker op 'print' drukken moet niet kunnen (knop disablen en op basis van polling (isPrinting?) status up-to-date houden)
|
|
||||||
-> maar! de firmware moet geen nieuwe printopdrachten accepteren wanneer er al een print bezig is
|
|
||||||
* temperatuurindicatie (alleen wanneer temperatuuruitlezing via api mogelijk is) -> dus ook indicatie van draaiende printserver
|
|
||||||
- (misschien?) verticale shape aanpassen
|
|
||||||
- preheaten voor het starten van een print
|
|
||||||
* (fw) wachten op targettemperatuur - 20 graden (hoe om te gaan met afkoelen?)
|
|
||||||
* (client) in config bij temperatuurinstelling: opmerking dat de printer gaat printen vanaf lagere temperatuur (bv. -20)
|
|
||||||
|
|
||||||
## te den voor final release
|
|
||||||
- start/end-codes configureerbaar maken (via los endpoint) (duplicate)
|
|
||||||
- printerlijst opvragen
|
|
||||||
* data: per printer: {id, path, type}
|
|
||||||
- gcode: printer busy rapporteren vanaf moment dat gcode wordt verzameld, niet pas bij begin printen (of gcode verzamelen per remote host?)
|
|
||||||
- op wiki over openwrt/osx svn checkout veranderen naar git clone
|
|
||||||
- image met alles erin
|
|
||||||
* in postinst op kastje: ook wifibox start doen (enable doet dat niet) (ook voor ultifi)
|
|
||||||
* firewall net wordt nog niet aangemaakt in 'Y'-mode
|
|
||||||
- nadenken over loggen (procedure voor testers hoe ze problemen kunnen rapporteren zodat wij ze kunnen reproduceren)
|
|
||||||
* verzamelen+zippen van logread output (of uci system.@system[0].log_file?) + /tmp/wifibox.conf + printserver log
|
|
||||||
- na /network/disassociate is wifi uitgeschakeld -> kan geen macadres opvragen -> openap bv. 2x nodig om weer goed macadres te vinden
|
|
||||||
- client: netwerkkeuze toevoegen?
|
|
||||||
- herstart van uhttpd en reboot uitstellen tot na sturen van response (closure queue in response.lua)
|
|
||||||
- consistentie REST API
|
|
||||||
- code documenteren
|
|
||||||
- codedocs uitwerken naar apidocs
|
|
||||||
- optie voor loggen toevoegen aan printmanager
|
|
||||||
- AP en client tegelijk (VAP / multi-ssid?)
|
|
||||||
* toegang altijd via AP, clientmode alleen voor updaten en internet ook via kastje (dan moet wel de portalmodus uit)
|
|
||||||
* dns forward: list 'dhcp_option' '6,10.0.0.1,192.168.178.1' (<http://wiki.openwrt.org/doc/howto/dhcp.dnsmasq#configuring.dnsmasq.to.broadcast.external.dns.server.information>)
|
|
||||||
- auto-update (zowel package als geheel image; <- kijken hoe luci dat doet)
|
|
||||||
- serieel:
|
|
||||||
* 115k2? -> Peter zei iets over instabiele connectie op 250k?
|
|
||||||
* fallback lijkt niet te werken (zelfde probleem als bij poort opnieuw openen?)
|
|
||||||
* mss helpt arduino reset triggeren om port opnieuw te kunnen openen?
|
|
||||||
* 3e manier baudrate zetten? <http://stackoverflow.com/questions/4968529/how-to-set-baud-rate-to-307200-on-linux>
|
|
||||||
- initscript testen (lijkt vaker dan eens te worden uitgevoerd)
|
|
||||||
- printerExists: ook nagaan of basispad ultifi bestaat?
|
|
||||||
|
|
||||||
|
|
||||||
## OOK MEE BEZIG
|
|
||||||
- in AP mode, things like 'somewhere.org/asdsfd' still results in 'Not found'
|
|
||||||
- behalve /dev/ttyACM* kan het voor FTDI dus ook /dev/ttyUSB* zijn
|
|
||||||
- config API: anders inrichten (misschien toch 1 key per keer instellen zodat response 'fail' kan zijn?)
|
|
||||||
|
|
||||||
- auto-update
|
|
||||||
- source-url in Makefile aanpassen (type aanpassen naar git en dan direct naar github repo)
|
|
||||||
- toevoegen aan /etc/opkg.conf via files in image: `src/gz wifibox http://doodle3d.com/static/wifibox-packages`
|
|
||||||
- of lokaal: `src/gz wifibox file:///tmp/wifibox-packages`
|
|
||||||
- (info) feed update-script: <wifibox_git_root>/extra/create-packages-dir.sh
|
|
||||||
uitvoeren vanuit pad waar wifibox_packages terecht moet komen (bv. ~/Sites)
|
|
||||||
- (info) package-url: <http://doodle3d.com/static/wifibox/packages>
|
|
||||||
- (info) image-url: <http://doodle3d.com/static/wifibox/images>
|
|
||||||
- later: printerprofielen
|
|
||||||
|
|
||||||
- API:
|
|
||||||
api/info/currentVersion
|
|
||||||
api/info/latestVersion [beta=true]
|
|
||||||
api/system/update
|
|
||||||
api/system/flash
|
|
||||||
* wat als wij een verkeerd package releasen waardoor de API niet meer werkt?
|
|
||||||
|
|
||||||
- (ref) <http://wiki.openwrt.org/doc/devel/packages/opkg>
|
|
||||||
- (ref) <http://wiki.openwrt.org/doc/techref/opkg>
|
|
||||||
- (ref) <http://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/>
|
|
||||||
- waar moeten debugvlaggen etc naartoe? (run_flags.lua?)
|
|
||||||
- in package postinst: hostname van kastje instellen op wifibox (met mac?)
|
|
||||||
|
|
||||||
- tijdens openwrt make:
|
|
||||||
'* satisfy_dependencies_for: Cannot satisfy the following dependencies for kmod-ath9k-common:
|
|
||||||
'* kmod-crypto-hash *
|
|
||||||
- wiki bijwerken (links, structuur, API)
|
|
||||||
- ook in wiki, luadoc installeren:
|
|
||||||
* !! (beter vervangen door?) <http://stevedonovan.github.io/ldoc/topics/doc.md.html>
|
|
||||||
* ongeveer volgens <http://www.hobsie.com/mark/archives/33>, maar! :
|
|
||||||
* luasocket apart installeren met `sudo luarocks install https://raw.github.com/diegonehab/luasocket/master/luasocket-scm-0.rockspec`
|
|
||||||
- Code documenteren <http://keplerproject.github.io/luadoc/>
|
|
||||||
- Lua programmeerstijl? (enkele quotes gebruiken behalve voor i18n)
|
|
||||||
- zoals het nu werkt wordt het lastig om een hiërarchische api te ondersteunen zoals dit: <http://www.restapitutorial.com/lessons/restfulresourcenaming.html>
|
|
||||||
- uhttpd ondersteunt geen PUT en DELETE, wel status codes. Beschrijving CGI-antwoorden: <http://docstore.mik.ua/orelly/linux/cgi/ch03_03.htm>
|
|
||||||
- voor captive portal: cgi 'Location' header voor redirect naar goede url?
|
|
||||||
|
|
||||||
- http statuscodes <https://blog.apigee.com/detail/restful_api_design_what_about_errors>; met relevante link in antwoord (meer: <https://blog.apigee.com/taglist/restful>)
|
|
||||||
- proposed status handling in response.lua:
|
|
||||||
fucntion setStatus(code, <msg>) -> sets http status+dfl msg and optional errmsg in data
|
|
||||||
|
|
||||||
# TODO (new functionality)
|
|
||||||
- fix init script handling as described here: http://wiki.openwrt.org/doc/devel/packages#packaging.a.service
|
|
||||||
- implement (automated) test code where possible
|
|
||||||
* in 'test' dir next to 'src', with API tests under 'test/www/'
|
|
||||||
* www tests check functionality of the test module
|
|
||||||
* www tests also provide an interface to run arbitrary get/post requests
|
|
||||||
* test path splitting as well
|
|
||||||
- document REST API
|
|
||||||
* fail/error difference: fail is a valid rq aka 'could not comply', while error is invalid rq _or_ system error
|
|
||||||
* modules/functions prefixed with '_' are for internal use
|
|
||||||
* rq IDs and endpoint information can be supplied (but it's probably not useful after all)
|
|
||||||
* list endpoints+args+CRUD type
|
|
||||||
* success/fail/error statuses are justified by drupal api
|
|
||||||
* unknown values (e.g. in network info) are either empty or unmentioned fields
|
|
||||||
- define a list of REST error codes to be more descriptive for clients (e.g. errortype=system/missing-arg/generic)
|
|
||||||
- steps to take regarding versioning/updating
|
|
||||||
* versioning scheme
|
|
||||||
* create feed location (e.g. www.doodle3d.com/firmware/packages) (see here: http://wiki.openwrt.org/doc/packages#third.party.packages)
|
|
||||||
* create opkg (already present in bin/ar71xx/packages as .ipk file)
|
|
||||||
* create listing info for package list (checksum, size, etc. ...is this inside the .ipk file?)
|
|
||||||
* find a way to add the feed url to opkg.conf (directly in files during image building?)
|
|
||||||
* determine how opkg decides what is 'upgradeable'
|
|
||||||
* at this point manual updating should be possible, now find out how to implement in lua (execve? or write a minimalistic binding to libopkg?)
|
|
||||||
* expose through info API and/or system API; also provide a way (future) to flash a new image
|
|
||||||
- generally, for configuration keys, it could be a good idea to use the concept of default values so it's always possible to return to a 'sane default config'
|
|
||||||
* use a uci wifibox config to store configuration and a uci wifibox-defaults config as fallback-lookup (which contains a complete default configuration)
|
|
||||||
* specify min/max/type/regex for each config key in separate lua file
|
|
||||||
* perhaps defaults should be specified together with min/max/type/regex
|
|
||||||
- dynamic AP name based on partial MAC (present in default config so it can be overridden and reverted again)
|
|
||||||
- require api functions which change state to be invoked as post request
|
|
||||||
* can this be modelled like java annotations or c function attributes?
|
|
||||||
* otherwise maybe pair each function with <func>_attribs = {…}?
|
|
||||||
- add API functions to test network connectivity in steps (any chance(e.g. ~ap)? ifup? hasip? resolve? ping?) to network or test
|
|
||||||
- handling requests which need a restart of uhttpd (e.g. network/openap) will probably respond with some kind of 'please check back in a few seconds' response
|
|
||||||
- add more config options to package, which should act as defaults for a config file on the system; candidates:
|
|
||||||
reconf.WWW_RENAME_NAME, wifihelper.{AP_ADDRESS, AP_NETMASK, (NET)}
|
|
||||||
<https://github.com/2ion/ini.lua>
|
|
||||||
|
|
||||||
|
|
||||||
# Ideas / issues to work out
|
|
||||||
- add system api module? for check-updates/do-update/etc
|
|
||||||
- licensing (also for hardware and firmware) + credits for external code and used ideas (<http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html>)
|
|
||||||
- (this is an old todo item from network:available(), might still be relevant at some point)
|
|
||||||
extend netconf interface to support function arguments (as tables) so wifihelper functionality can be integrated
|
|
||||||
but how? idea: pass x_args={arg1="a",arg2="2342"} for component 'x'
|
|
||||||
or: allow alternative for x="y" --> x={action="y", arg1="a", arg2="2342"}
|
|
||||||
in any case, arguments should be put in a new table to pass to the function (since order is undefined it must be an assoc array)
|
|
||||||
- perhaps opkg+safeboot could be useful in the update mechanism?
|
|
||||||
- add config option to compile sources using luac _or_ add an option to minify the lua code
|
|
||||||
|
|
||||||
|
|
||||||
# Bugs
|
|
||||||
- (captive portal mode) https is not redirected
|
|
||||||
- (captive portal mode) .local domains are not redirected
|
|
||||||
- (captive portal mode) any urls with text after the root domain are not redirected
|
|
||||||
- using iwinfo with interface name 'radio0' yields very little 'info' output while wlan0 works fine.
|
|
||||||
However, sometimes wlan0 disappears (happened after trying to associate with non-existing network)...why?
|
|
||||||
- protect dump function against reference loops (see <http://lua-users.org/wiki/TableSerialization>, json also handles this well)
|
|
||||||
- relocatabilty of package (take root prefix into consideration everywhere)
|
|
||||||
- disabling all wireless networks breaks the current method of obtaining the mac address, thus openap must be called twice before it is properly set up
|
|
||||||
|
|
||||||
|
|
||||||
# Logos
|
|
||||||
|
|
||||||
Check <http://geon.github.io/Programming/2012/04/25/ascii-art-signatures-in-the-wild/> for inspiration.
|
|
||||||
|
|
||||||
|
|
||||||
D o o d l e 3 D
|
|
||||||
-------- ____ .--- v 1.0.1
|
|
||||||
| | | | __ | __|.--.| ._| .---..-.-.
|
|
||||||
| | | ||--|| _| |--|| . || . |\ /
|
|
||||||
|________||__||__| |__||____||___|/_._\
|
|
||||||
|
|
||||||
|
|
||||||
D o o d l e 3 D
|
|
||||||
-------- ____ .---- v 1.0.1
|
|
||||||
| | | |--.| __|-.| ._|---.-.-.
|
|
||||||
| | | |--|| _|--|| . | . |_ _/
|
|
||||||
|________|__||__||__||____|___|_._\
|
|
||||||
|
|
||||||
|
|
||||||
....D o o d l e 3 D
|
|
||||||
...________ _____ _____ v 1.0.1
|
|
||||||
../ / / |__ / __/ / - /___ __
|
|
||||||
./ ' ' /--// _|-// - | . /v /
|
|
||||||
/________/__//__/__//____/___/_^_\
|
|
@ -8,6 +8,8 @@ local main = require('main')
|
|||||||
-- The table is created using shell environment variables leaving out only 'DOCUMENT\_ROOT',
|
-- The table is created using shell environment variables leaving out only 'DOCUMENT\_ROOT',
|
||||||
-- 'SCRIPT\_PATH' and the regular shell variables (e.g., IFS, HOME and PS1).
|
-- 'SCRIPT\_PATH' and the regular shell variables (e.g., IFS, HOME and PS1).
|
||||||
--
|
--
|
||||||
|
-- See [information on CGI environment variables](http://techpubs.sgi.com/library/dynaweb_docs/0530/SGI_Developer/books/NetscapeSrv_PG/sgi_html/ch01.html).
|
||||||
|
--
|
||||||
-- Fields present in the 'real' env table but not in this one are: 'HTTP\_VERSION'
|
-- Fields present in the 'real' env table but not in this one are: 'HTTP\_VERSION'
|
||||||
-- and another table 'headers' which is mostly mirrored by the 'HTTP\_*' fields.
|
-- and another table 'headers' which is mostly mirrored by the 'HTTP\_*' fields.
|
||||||
-- Note that the 'headers' table may contain extra fields (e.g., 'cache-control').
|
-- Note that the 'headers' table may contain extra fields (e.g., 'cache-control').
|
||||||
|
24
src/main.lua
24
src/main.lua
@ -1,5 +1,8 @@
|
|||||||
---
|
---
|
||||||
-- Entry code of the REST API. This sets up the environment, processes a REST request and responds appropiately.
|
-- Entry code of the REST API and secondary functionality.
|
||||||
|
-- Primarily, this sets up the environment, processes a REST request and responds appropiately.
|
||||||
|
-- Secondary functions are to auto-switch between access point and client (@{setupAutoWifiMode})
|
||||||
|
-- and to signin to [connect.doodle3d.com](http://connect.doodle3d.com/) (@{network.signin}).
|
||||||
package.path = package.path .. ';/usr/share/lua/wifibox/?.lua'
|
package.path = package.path .. ';/usr/share/lua/wifibox/?.lua'
|
||||||
|
|
||||||
local confDefaults = require('conf_defaults')
|
local confDefaults = require('conf_defaults')
|
||||||
@ -15,6 +18,11 @@ local Signin = require('network.signin')
|
|||||||
local postData = nil
|
local postData = nil
|
||||||
|
|
||||||
|
|
||||||
|
--- Switches to wifi client mode or to access point mode based on availability of known wifi networks.
|
||||||
|
--
|
||||||
|
-- If the configuration has actively been set to access point mode, that will always be selected.
|
||||||
|
-- If not, it will be attempted to connect to a known network (in order of recency) and only if
|
||||||
|
-- that fails, access point mode will be selected as fall-back.
|
||||||
local function setupAutoWifiMode()
|
local function setupAutoWifiMode()
|
||||||
-- expects list with tables containing 'ssid' key as values and returns index key if found or nil if not found
|
-- expects list with tables containing 'ssid' key as values and returns index key if found or nil if not found
|
||||||
local function findSsidInList(list, name)
|
local function findSsidInList(list, name)
|
||||||
@ -84,6 +92,11 @@ local function setupAutoWifiMode()
|
|||||||
return nil, "autowifi: uh oh - bad situation in autowifi function"
|
return nil, "autowifi: uh oh - bad situation in autowifi function"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the logging system to use the file and level defined in the system settings.
|
||||||
|
-- The settings used are `logfile` and `loglevel`. The former may either be a
|
||||||
|
-- reular file path, or `<stdout>` or `<stderr>`.
|
||||||
|
-- @see util.settings.getSystemKey
|
||||||
|
-- @treturn bool True on success, false on error.
|
||||||
local function setupLogger()
|
local function setupLogger()
|
||||||
local logStream = io.stderr -- use stderr as hard-coded default target
|
local logStream = io.stderr -- use stderr as hard-coded default target
|
||||||
local logLevel = log.LEVEL.debug -- use debug logging as hard-coded default level
|
local logLevel = log.LEVEL.debug -- use debug logging as hard-coded default level
|
||||||
@ -135,6 +148,9 @@ local function setupLogger()
|
|||||||
return rv
|
return rv
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the environment.
|
||||||
|
-- The logger is set up, any POST data is read and several other subsystems are initialized.
|
||||||
|
-- @tparam table environment The 'shell' environment containing all CGI variables. Note that @{cmdmain} simulates this.
|
||||||
local function init(environment)
|
local function init(environment)
|
||||||
setupLogger()
|
setupLogger()
|
||||||
|
|
||||||
@ -162,6 +178,9 @@ local function init(environment)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Decides what action to take based on shell/CGI parameters.
|
||||||
|
-- Either executes a REST request, or calls @{setupAutoWifiMode} or @{network.signin}.
|
||||||
|
-- @tparam table environment The CGI environment table.
|
||||||
local function main(environment)
|
local function main(environment)
|
||||||
local rq = RequestClass.new(environment, postData, confDefaults.DEBUG_API)
|
local rq = RequestClass.new(environment, postData, confDefaults.DEBUG_API)
|
||||||
|
|
||||||
@ -210,7 +229,8 @@ local function main(environment)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Firmware entry point.
|
--- Firmware entry point. Runs @{init} and calls @{main}.
|
||||||
|
--
|
||||||
-- This is either used by [uhttp-mod-lua](http://wiki.openwrt.org/doc/uci/uhttpd#embedded.lua)
|
-- This is either used by [uhttp-mod-lua](http://wiki.openwrt.org/doc/uci/uhttpd#embedded.lua)
|
||||||
-- directly, or by the d3dapi cgi-bin wrapper script which builds the env table
|
-- directly, or by the d3dapi cgi-bin wrapper script which builds the env table
|
||||||
-- from the shell environment. The wrapper script also handles command-line invocation.
|
-- from the shell environment. The wrapper script also handles command-line invocation.
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
---
|
||||||
|
-- TODO: document
|
||||||
local log = require('util.logger')
|
local log = require('util.logger')
|
||||||
local utils = require('util.utils')
|
local utils = require('util.utils')
|
||||||
local uci = require('uci').cursor()
|
local uci = require('uci').cursor()
|
||||||
@ -15,40 +17,40 @@ local IDLE_STATUS = 1
|
|||||||
local SIGNING_IN_STATUS = 2
|
local SIGNING_IN_STATUS = 2
|
||||||
|
|
||||||
--- Signin to connect.doodle3d.com server
|
--- Signin to connect.doodle3d.com server
|
||||||
--
|
--
|
||||||
function M.signin()
|
function M.signin()
|
||||||
|
|
||||||
--log:debug("signin:signin");
|
--log:debug("signin:signin");
|
||||||
|
|
||||||
local code, msg = M.getStatus()
|
local code, msg = M.getStatus()
|
||||||
--log:debug(" status: "..utils.dump(code).." "..utils.dump(msg));
|
--log:debug(" status: "..utils.dump(code).." "..utils.dump(msg));
|
||||||
|
|
||||||
-- if we are already signin in, skip
|
-- if we are already signin in, skip
|
||||||
if(code == SIGNING_IN_STATUS) then
|
if(code == SIGNING_IN_STATUS) then
|
||||||
log:debug(" skipping signin")
|
log:debug(" skipping signin")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
M.setStatus(SIGNING_IN_STATUS,"signing in")
|
M.setStatus(SIGNING_IN_STATUS,"signing in")
|
||||||
|
|
||||||
local baseurl = "http://connect.doodle3d.com/api/signin.php"
|
local baseurl = "http://connect.doodle3d.com/api/signin.php"
|
||||||
|
|
||||||
local localip = wifi.getLocalIP();
|
local localip = wifi.getLocalIP();
|
||||||
if localip == nil then
|
if localip == nil then
|
||||||
log:error("signin failed no local ip found")
|
log:error("signin failed no local ip found")
|
||||||
M.setStatus(IDLE_STATUS,"idle")
|
M.setStatus(IDLE_STATUS,"idle")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local wifiboxid = wifi.getSubstitutedSsid(settings.get('network.cl.wifiboxid'))
|
local wifiboxid = wifi.getSubstitutedSsid(settings.get('network.cl.wifiboxid'))
|
||||||
wifiboxid = urlcode.escape(wifiboxid)
|
wifiboxid = urlcode.escape(wifiboxid)
|
||||||
|
|
||||||
local cmd = "wget -q -T 2 -t 1 -O - "..baseurl.."?wifiboxid="..wifiboxid.."\\&localip="..localip;
|
local cmd = "wget -q -T 2 -t 1 -O - "..baseurl.."?wifiboxid="..wifiboxid.."\\&localip="..localip;
|
||||||
local output = utils.captureCommandOutput(cmd);
|
local output = utils.captureCommandOutput(cmd);
|
||||||
log:info("signin: "..output)
|
log:info("signin: "..output)
|
||||||
|
|
||||||
M.setStatus(IDLE_STATUS,"idle")
|
M.setStatus(IDLE_STATUS,"idle")
|
||||||
|
|
||||||
return string.len(output) > 0, output
|
return string.len(output) > 0, output
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -61,4 +63,4 @@ function M.setStatus(code,msg)
|
|||||||
status.set(STATUS_FILE,code,msg);
|
status.set(STATUS_FILE,code,msg);
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
---
|
---
|
||||||
-- The unavoidable collection of utility functions.
|
-- The unavoidable collection of utility functions.
|
||||||
-- TODO: use macros/type definitions to document rest modules (to auto-match things like 'M.<func>_NAME%')?
|
--
|
||||||
|
-- Functions in this file are accompanied by unit tests, please study those
|
||||||
|
-- to see how utility functions are expected to behave.
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
|
||||||
|
--- Splits a string on a given divider character.
|
||||||
|
-- @string[opt=':'] div The divider character to use.
|
||||||
|
-- @return An array containing the resultant substrings.
|
||||||
|
-- @usage local str = "a,b,c"; local parts = str:split(',')
|
||||||
function string:split(div)
|
function string:split(div)
|
||||||
local div, pos, arr = div or ':', 0, {}
|
local div, pos, arr = div or ':', 0, {}
|
||||||
for st,sp in function() return self:find(div, pos, true) end do
|
for st,sp in function() return self:find(div, pos, true) end do
|
||||||
@ -15,6 +21,9 @@ function string:split(div)
|
|||||||
return arr
|
return arr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the size of an open file handle.
|
||||||
|
-- @param file File handle to report about.
|
||||||
|
-- @treturn number Size of the file, determined by seeking to the end.
|
||||||
function M.fileSize(file)
|
function M.fileSize(file)
|
||||||
local current = file:seek()
|
local current = file:seek()
|
||||||
local size = file:seek('end')
|
local size = file:seek('end')
|
||||||
@ -22,6 +31,11 @@ function M.fileSize(file)
|
|||||||
return size
|
return size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Convert an object to boolean.
|
||||||
|
-- String values which will yield true are (case insensitive): '1', 't' and 'true'.
|
||||||
|
-- Boolean true and numbers other than 0 also yield true, everything else yields false.
|
||||||
|
-- @param s The object to convert.
|
||||||
|
-- @treturn bool The converted value.
|
||||||
function M.toboolean(s)
|
function M.toboolean(s)
|
||||||
if not s then return false end
|
if not s then return false end
|
||||||
|
|
||||||
@ -32,6 +46,10 @@ function M.toboolean(s)
|
|||||||
return textTrue or boolTrue or numTrue
|
return textTrue or boolTrue or numTrue
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Stringifies the given object.
|
||||||
|
-- Note that self-referencing objects will cause an endless loop with the current implementation.
|
||||||
|
-- @param o The object to convert.
|
||||||
|
-- @treturn string Stringified version of o.
|
||||||
function M.dump(o)
|
function M.dump(o)
|
||||||
if type(o) == 'table' then
|
if type(o) == 'table' then
|
||||||
local s = '{ '
|
local s = '{ '
|
||||||
@ -58,6 +76,10 @@ function M.getUciSectionName(config, type)
|
|||||||
return sname
|
return sname
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Reports whether or not a file exists. This is done by trying to open it.
|
||||||
|
-- @tparam string file Filename to report about.
|
||||||
|
-- @treturn bool|nil True if the file exists, false otherwise or nil on invalid argument.
|
||||||
|
-- @treturn ?string Descriptive message on error.
|
||||||
function M.exists(file)
|
function M.exists(file)
|
||||||
if not file or type(file) ~= 'string' or file:len() == 0 then
|
if not file or type(file) ~= 'string' or file:len() == 0 then
|
||||||
return nil, "file must be a non-empty string"
|
return nil, "file must be a non-empty string"
|
||||||
@ -68,7 +90,10 @@ function M.exists(file)
|
|||||||
return r ~= nil
|
return r ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--creates and returns true if not exists, returns false it does, nil+msg on error
|
--- Creates a file if it does not exist yet.
|
||||||
|
-- @string file Path and name of the file to create.
|
||||||
|
-- @treturn bool|nil True if the file has been created, false if it already existed or nil on error
|
||||||
|
-- @treturn ?string Descriptive message on error
|
||||||
function M.create(file)
|
function M.create(file)
|
||||||
local r,m = M.exists(file)
|
local r,m = M.exists(file)
|
||||||
|
|
||||||
@ -85,7 +110,12 @@ function M.create(file)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--FIXME: somehow protect this function from running arbitrary commands
|
--- Create a symlink on the file system.
|
||||||
|
-- _Note_ that this function contains a potential security leak as it uses os.execute with given parameters.
|
||||||
|
-- @string from Source path for the symlink.
|
||||||
|
-- @string to Target path for the symlink.
|
||||||
|
-- @return The return value from @{os.execute}, or -1 on invalid parameter(s).
|
||||||
|
-- @fixme: somehow protect this function from running arbitrary commands
|
||||||
function M.symlink(from, to)
|
function M.symlink(from, to)
|
||||||
if from == nil or from == '' or to == nil or to == '' then return -1 end
|
if from == nil or from == '' or to == nil or to == '' then return -1 end
|
||||||
local x = 'ln -s ' .. from .. ' ' .. to
|
local x = 'ln -s ' .. from .. ' ' .. to
|
||||||
@ -102,12 +132,15 @@ function M.readFile(filePath)
|
|||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: this function has been duplicated from rest/api/api_system.lua
|
--- Runs a command and captures its output using @{io.popen}.
|
||||||
|
-- @string cmd The command to run.
|
||||||
|
-- @treturn string Output of the command that was run.
|
||||||
|
-- @todo: this function has been duplicated from rest/api/api_system.lua
|
||||||
function M.captureCommandOutput(cmd)
|
function M.captureCommandOutput(cmd)
|
||||||
local f = assert(io.popen(cmd, 'r'))
|
local f = assert(io.popen(cmd, 'r'))
|
||||||
local output = assert(f:read('*all'))
|
local output = assert(f:read('*all'))
|
||||||
f:close()
|
f:close()
|
||||||
return output;
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
Loading…
Reference in New Issue
Block a user