From 373be38a103b307f9e7fb1d59506368c305e2b01 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sat, 11 Aug 2018 23:52:22 +0100 Subject: [PATCH] Rework in light of LFS --- README.rst | 22 ++++++------- init.lua | 57 ++++++++++++++++++++++++++++------ net/fifosock.lua | 2 +- net/nwfnet-go.lua | 2 +- telnetd/telnetd-file.lua | 3 ++ telnetd/telnetd.lua | 6 ++-- test/fifosocktest.lua | 67 ++++++++++++++++++++++++++++++++++++++++ test/morse.lua | 6 ++++ tq/tq-diag.lua | 2 +- util/diag.lua | 10 ++++++ util/lfs-strings.lua | 16 ++++++++++ 11 files changed, 166 insertions(+), 27 deletions(-) create mode 100644 test/fifosocktest.lua create mode 100644 test/morse.lua create mode 100644 util/lfs-strings.lua diff --git a/README.rst b/README.rst index 19619d5..fe89ded 100644 --- a/README.rst +++ b/README.rst @@ -6,9 +6,9 @@ Introduction ############ This is a collection of Lua modules I've used in various nodemcu/ESP8266 -projects. It's largely an overlay-style approach to code residency; many -things are intended to be ``dofile()``'d or ``loadfile()``'d and kept around -only while being used. +projects. It's largely an overlay-style approach to code residency: most +things are fetched through the ``OVL`` table created by ``init.lua`` rather +than ``require``. The files here are available under the GNU Affero General Public License, version 3 or later. See ``COPYING`` for details. @@ -27,7 +27,7 @@ Generic Utilities * ``util/diag.lua`` -- a simple set of diagnostic calls intended for general calling from the command line. A quick overview of the device. Use as - ``dofile("diag.lc")``. + ``OVL.diag()``. * ``host/pushinit.sh`` -- a host-side utility to push a minimum set of files up to the device, either via `luatool @@ -45,15 +45,15 @@ Networking Utilities Networking Framework -------------------- -* ``net/nwfnet.lua`` -- an event dispatch module; intended to be resident at - all times. +* ``net/nwfnet.lua`` -- an event dispatch module; load with require so that + there is a singleton instance. * ``nwfnet-diag.lua`` -- generic event reporting using the above; intended - as diagnostics from console. Use as ``dofile("nwfnet-diag.lc")(true)`` to - enable or ``...(false)`` to disable and unload. + as diagnostics from console. Use as ``OVL["nwfnet-diag"]()(true)`` to + enable or ``...(false)`` to disable. * ``net/nwfnet-go.lua`` -- bring up the network and dispatch events via - ``nwfnet`` above. Use via ``dofile``. + ``nwfnet`` above. Use via ``OVL``. * ``net/netnet-sntp.lua`` -- utilities for invoking SNTP time synchronization once or repeatedly (using ``tq``, below). Reads server @@ -103,9 +103,9 @@ Timer Queue Enqueue events with ``:queue(time,function,args...)``; ``:queue`` returns a handle suitable for use with ``:dequeue()`` to unregister a pending future event. All ESP-specific behavior is overridable by replacing - ``:now`` and ``:arm``. Use as ``tq = dofile("tq.lc")(timer)``. + ``:now`` and ``:arm``. Use as ``tq = OVL.tq()(timer)``. * ``tq/tq-diag.lua`` -- knows how to traverse a ``tq`` for diagnostic - utility. Use as ``dofile("tq-diag.lc")(tq,print,print)``, e.g. + utility. Use as ``OVL["tq-diag"]()(tq,print,print)``, e.g. diff --git a/init.lua b/init.lua index 389b458..5957601 100644 --- a/init.lua +++ b/init.lua @@ -1,16 +1,54 @@ --- DEPEND: file?, gpio, node, rtctime?, tmr ; nwfnet, nwfnet-diag, nwfnet-go, telnetd +-- DEPEND: gpio, node, rtctime?, tmr ; nwfnet, nwfnet-diag, nwfnet-go, telnetd + +-- An "overlay" table: load files or flash components in a way +-- that, unlike require, doesn't cause them to "stick" in RAM. +-- +-- Based on lua_examples/lfs/_init.lua +local G=getfenv() +local flashindex = node.flashindex +local ovl_t = { + __index = function(_, name) + local f = loadfile(name..".lua") + if f then return f end + local f = loadfile(name..".lc") + if f then return f end + if flashindex then + local fn_ut, ba, ma, size, modules = flashindex(name) + if not ba then return fn_ut end + end + return nil + end, + __newindex = function(_, name, value) + error("Overlay is a synthetic view! " .. name, 2) + end, + } +G.OVL = setmetatable(ovl_t,ovl_t) + +-- Install LFS as a package loader, as suggested by lua_examples/lfs/_init.lua +if flashindex then + table.insert(package.loaders,function(module) + local fn, ba = flashindex(module) + return ba and "Module not in LFS" or fn + end) +end + +-- Save some bytes, as suggested by lua_examples/lfs/_init.lua +G.module = nil +package.seeall = nil + if rtctime then rtctime.set(0) end -- set time to 0 until someone corrects us -- See if there's any early startup to do. -if file and file.exists("init-early.lua") then dofile("init-early.lua") end +local ie = OVL["init-early"] +if ie then ie() end local function goab() - dofile("nwfnet-diag.lc")(true) - dofile("diag.lc") - dofile("nwfnet-go.lc") + OVL["nwfnet-diag"]()(true) + OVL["diag"]() + OVL["nwfnet-go"]() tcpserv = net.createServer(net.TCP, 180) tcpserv:listen(23,function(k) - local telnetd = dofile "telnetd.lc" + local telnetd = OVL["telnetd"]() telnetd.on["conn"] = function(s) tmr.unregister(6) s(string.format("NODE-%06X RECOVERY (auto reboot cancelled)",node.chipid())) @@ -18,11 +56,10 @@ local function goab() telnetd.server(k) end) end -local function gof(fn) - local f, e = loadfile(fn) - if f == nil then print("Error:",fn,e); goab() else node.task.post(f) end +local function goi2() + local i2 = OVL.init2 + if not i2 then goab() else node.task.post(i2) end end -local function goi2() gof("init2.lc") end local function waitFLASH() local function stop_() gpio.mode(3,gpio.INPUT); gpio.trig(3); tmr.unregister(6) diff --git a/net/fifosock.lua b/net/fifosock.lua index 87cf26c..2dfe7d4 100644 --- a/net/fifosock.lua +++ b/net/fifosock.lua @@ -8,7 +8,7 @@ local FSMALLLIM = 32 -- maximum number of small strings held local concat = table.concat local insert = table.insert -local fifo = (require "fifo")() +local fifo = OVL.fifo() return function(sock) local ssend = function(s) sock:send(s) end diff --git a/net/nwfnet-go.lua b/net/nwfnet-go.lua index d89d2b7..4579cae 100644 --- a/net/nwfnet-go.lua +++ b/net/nwfnet-go.lua @@ -2,7 +2,7 @@ wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function(t) (require "nwfnet"):runnet("wstagoip",t) if mdns then mdns.register(wifi.sta.gethostname()) end - dofile("nwfnet-sntp.lc").dosntp(nil) + OVL["nwfnet-sntp"]().dosntp(nil) end) wifi.eventmon.register(wifi.eventmon.STA_DHCP_TIMEOUT, function(_) (require "nwfnet"):runnet("wstadtmo") end) wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(t) (require "nwfnet"):runnet("wstaconn",t) end) diff --git a/telnetd/telnetd-file.lua b/telnetd/telnetd-file.lua index 4578d6b..f7d4716 100644 --- a/telnetd/telnetd-file.lua +++ b/telnetd/telnetd-file.lua @@ -12,6 +12,9 @@ return { , ["compile"] = function(ll,s) local fn = string.match(ll,"^%s*([^%s]+)%s*$"); local r,err = pcall(node.compile,fn); if not r then s("ERR: "..err) end end +, ["flashreload"] = function(ll,s) local fn = string.match(ll,"^%s*([^%s]+)%s*$"); + local r,err = pcall(node.flashreload,fn); if not r then s("ERR: "..err) end + end , ["sha256"] = function(ll,s) -- compute the hash of a file in flash local fn = string.match(ll,"^%s*([^%s]+)%s*$") s(crypto.toBase64(crypto.fhash('sha256',fn))) diff --git a/telnetd/telnetd.lua b/telnetd/telnetd.lua index e9fa599..9b0d4a6 100644 --- a/telnetd/telnetd.lua +++ b/telnetd/telnetd.lua @@ -15,8 +15,8 @@ function self.rx(tx,input,k) self.tryin(input, self.commands, function(c,r) if c == "quit" then k(false) else - local rt = loadfile(string.format("telnetd-%s.lc",c)) - if rt ~= nil + local rt = OVL["telnetd-"..c] + if type(rt) == 'function' then self.tryin(r,rt(),function(c2) tx(c.." "..c2.."?") end, function() tx(c.." ??") end,tx) else tx(c.."?") end @@ -26,7 +26,7 @@ function self.rx(tx,input,k) function(_) tx("?") k(true) end,tx) end function self.server(sock_) - local fsend = (dofile("fifosock.lc"))((require "fifo")(), sock_) + local fsend = OVL.fifosock()(sock_) local function teardown(rawsock) rawsock:on("sent", nil) rawsock:on("receive", nil) diff --git a/test/fifosocktest.lua b/test/fifosocktest.lua new file mode 100644 index 0000000..2efdc3f --- /dev/null +++ b/test/fifosocktest.lua @@ -0,0 +1,67 @@ +OVL={} +OVL.fifo = function() return dofile("./fifo/fifo.lua") end +package.loaded["fifosock"] = dofile("./net/fifosock.lua") + +-- vprint = print +vprint = function() end +outs = {} + +fakesock = { + cb = nil, + on = function(this, _, cb) vprint("CBSET") this.cb = cb end, + send = function(this, s) vprint("SEND", verbose and s) table.insert(outs, s) end, +} +function sent() vprint("CB") fakesock.cb() end + +fsend = require "fifosock" (fakesock) +function fcheck(x) + vprint ("CHECK", verbose and x) + assert (#outs > 0) + assert (x == outs[1]) + table.remove(outs, 1) +end +function fsendc(x) fsend(x) fcheck(x) end +function fchecke() vprint("CHECKE") assert (#outs == 0) end + +fsendc("abracadabra none") +sent() ; fchecke() + +fsendc("abracadabra three") +fsend("short") +fsend("string") +fsend("build") +sent() ; fcheck("shortstringbuild") +sent() ; fchecke() + +-- Hit default FSMALLLIM while building up +fsendc("abracadabra lots small") +for i = 1, 34 do fsend("a") end +sent() ; fcheck(string.rep("a", 32)) +sent() ; fcheck("aa") +sent() ; fchecke() + +-- Hit string length while building up +fsendc("abracadabra overlong") +for i = 1, 10 do fsend(string.rep("a",32)) end +sent() ; fcheck(string.rep("a", 256)) +sent() ; fcheck(string.rep("a", 64)) +sent() ; fchecke() + +-- Hit neither before sending a big string +fsendc("abracadabra mid long") +for i = 1, 6 do fsend(string.rep("a",32)) end +fsend(string.rep("b", 256)) +for i = 1, 6 do fsend(string.rep("c",32)) end +sent() ; fcheck(string.rep("a", 192)) +sent() ; fcheck(string.rep("b", 256)) +sent() ; fcheck(string.rep("c", 192)) +sent() ; fchecke() + +-- send a huge string +fsend(string.rep("a",256) .. string.rep("b", 256) .. string.rep("c", 260)) +fcheck(string.rep("a",256)) +sent() ; fcheck(string.rep("b",256)) +sent() ; fcheck(string.rep("c",260)) +sent() ; fchecke() + +print("All tests OK") diff --git a/test/morse.lua b/test/morse.lua new file mode 100644 index 0000000..18e2f8c --- /dev/null +++ b/test/morse.lua @@ -0,0 +1,6 @@ +morse = dofile("morse/morse.lua") + +function tm(str) + local m = morse(str) + while m(print) do end +end diff --git a/tq/tq-diag.lua b/tq/tq-diag.lua index 129cced..5dbe357 100644 --- a/tq/tq-diag.lua +++ b/tq/tq-diag.lua @@ -1,3 +1,3 @@ -- call directly or wrap in tq immediately to get updated leader time value: --- tq:queue(1,function() dofile("tq-diag.lc")(tq,print,print) end) +-- tq:queue(1,function() OVL["tq-diag"]()(tq,print,print) end) return function (self,kt,ke) local i,t; for i,t in ipairs(self._q) do kt(i,t["t"],#t) for k,v in ipairs(t) do ke(i,k,v) end end end diff --git a/util/diag.lua b/util/diag.lua index 32d81af..7c31258 100644 --- a/util/diag.lua +++ b/util/diag.lua @@ -1,4 +1,5 @@ -- SOFT DEPENDS: file, rtcfifo, node, wifi +local k,v if node then print('INFO:',string.format("major=%d minor=%d dev=%d chip=%d flash=%d fs=%d fm=%d fs=%d",node.info())) print('HEAP:', node.heap()) @@ -17,5 +18,14 @@ end if file then print('FS:', file.fsinfo()); for k,v in pairs(file.list()) do print("",k,v) end end +if node.flashindex then + local ut, fa, ma, sz, t = node.flashindex() + if ut then + print('LFS:', ut, fa, ma, sz) + for k,v in ipairs(t) do print("", v) end + else + print('LFS:', fa, ma) + end +end print('PACKAGES:'); for k,v in pairs(package.loaded) do print("",k,v) end print('GLOBAL:'); for k,v in pairs(_G) do print("",k,v) end diff --git a/util/lfs-strings.lua b/util/lfs-strings.lua new file mode 100644 index 0000000..764c44c --- /dev/null +++ b/util/lfs-strings.lua @@ -0,0 +1,16 @@ +-- from lua_examples/lfs/dummy_strings.lua +local preload = "?.lc;?.lua", "/\n;\n?\n!\n-", "@init.lua", "_G", "_LOADED", +"_LOADLIB", "__add", "__call", "__concat", "__div", "__eq", "__gc", "__index", +"__le", "__len", "__lt", "__mod", "__mode", "__mul", "__newindex", "__pow", +"__sub", "__tostring", "__unm", "collectgarbage", "cpath", "debug", "file", +"file.obj", "file.vol", "flash", "getstrings", "index", "ipairs", "list", "loaded", +"loader", "loaders", "loadlib", "module", "net.tcpserver", "net.tcpsocket", +"net.udpsocket", "newproxy", "package", "pairs", "path", "preload", "reload", +"require", "seeall", "wdclr", "not enough memory", "sjson.decoder","sjson.encoder", +"tmr.timer" + +local initload = + ".lc", ".lua", "loadfile", + "Module not in LFS", + "NODE-%06X RECOVERY (auto reboot cancelled)", + "Overlay is a synthetic view! " -- 2.50.1