Post your best Lua script examples here

User avatar
By Patriko
#11722 No, it's not - I used this function based on this optimization method to provide network configuration:

Code: Select alllocal flash = {}

 function flash.ListAP(t)
    local res = ""
    if t then
      for k,v in pairs(t) do
        res = res .. '"' .. k .. '"' .. ",\n"
     if"aplist.txt","w+") then
          print("accesspoint list : " .. res .. " has ben written to aplist.txt file")

  function flash.GetAPList()
     local list = ""
     if"aplist.txt","r") then
          list =
     return list

return loadfile("")("config", {}, {}, flash)
User avatar
By dpwhittaker
#11765 First, I've been profiling the memory performance using this technique:


Code: Select allprint("start", node.heap())
config = flashMod("config")
print("before", node.heap())
wifi.sta.getap(function() print("hi") end)
print("after", node.heap())


Code: Select allprint("start", node.heap())
config = flashMod("config")
print("before", node.heap())
wifi.sta.getap(function(t) config.ListAP(t) end)
print("after", node.heap())

Note that they are identical except for the test version calls the config.ListAP in the callback, and the baseline version calls print("hi"). This gave me a way to determine if it was the function taking up heap or other lua overhead that I don't have control over, and both methods had nearly identical memory utilization, even on the original approach.

However, I did notice I was leaking some memory on the persistent environment of private and public methods, that the 4-way chain of __index calls was slowing things down even more than loading from flash, and a few other issues that the original approach had, so I decided to distill the approach down to its simplest possible form, and go for the lightest implementation I could imagine. And here is what I came up with:

Code: Select allflash = {MOD_NAME = "flash"}

function flash.flashMod(tbl)
   if type(tbl) == "string" then tbl = {MOD_NAME=tbl} end
   for k,v in pairs(tbl) do
      if type(v) == "function" then"", tbl.MOD_NAME, k), "w+")
         tbl[k] = nil
   return setmetatable(tbl, {
      __index = function(t, k)
         return assert(loadfile(string.format("",t.MOD_NAME,k)))

flash = nil
module = nil
package = nil
newproxy = nil
require = nil

function flashMod(tbl) return loadfile("")(tbl) end

Notice a few things here - I've completely gotten rid of the concept public/private/flash. Everything is considered a flash function at the time flashMod is called. So, if you want some in-memory functions, add them to the table after you call flashMod... simple enough. Also, it is no longer setting the environment of the flash functions, so there is no concept of a private variable. You could easily pass an environment table as the second argument to flashMod, and use it inside the __index function to set the environment of the function, but this creates a closure around the __index function, bloating memory requirements for a feature that is a nice to have. I'd suggest marking private functions and data with an _, or only accessing them from in-memory functions, which do have access to the local namespace of the module.

Also, flashMod has become a global function which just bootstraps the flashMod function into existence using its own technique. The idea was to replace the module/package/require functionality with a single flash function, so I went ahead and deleted those other functions from the global namespace, freeing up almost another 1k of heap.

The special value MOD_NAME has been added to the table to hold the name of the module (the first half of the flash function file name). This was done to remove another closure, reducing memory requirements of the function that does have to stay in memory: __index. At this point, I could move the metatable into the global environment, and reference the same metatable from every flash module. I'll have to do some profiling to see if this helps once I have several flash modules to work with.

flashMod can be called in two ways:

Code: Select allflashMod(table)
serializes all the functions on the table to flash, removes them, and augments the table with a metatable that loads the functions on demand.
Code: Select allflashMod("modName")
creates an empty table with the metatable populated. Use this if you want to create the module in one file with the first version, but don't need to attach any additional in-memory methods or data.

So, a full module with public, private, and flash methods will take this form now:

Code: Select allmod = { MOD_NAME = "my_mod"}

function mod.flashFunc1() end
function mod.flashFunc2() end

flashMod(mod) --everything before this is a flash function, everything after it is an in-memory public function

local function privateFunc() end --only visible to public and other private functions
local privateData  --ditto

function mod.publicFunc() end

return mod

The zip attached to the first post has the new version of the config module mentioned in previous posts, as well as a flash version of LLbin (I was tired of waiting for a dofile() to load LLbin, so now I have it as a flash function with a global wrapper that is loaded during init. Faster binary transfer startups with hardly any heap usage). Feel free to play with this new version.

Let me know what you think.
User avatar
By alon24
#11770 Great changes, I will look into them soon (i hope)

but can you please give us the oled sample, in this new form?
I have been messing with the old form trying to add the i2c back (still no results), and I would love to use this new way, with the spi sample adjusted to it, as refrence.

User avatar
By alon24
#11830 I need some help, I think I have a lack of understanding on what can access what, and it translates to not enough memory and general code not working.
I am trying to use your code, to do the i2c oled again, but I am failing, so I thought I'd ask for some help.

Here are my files, when I run I get kernel panic, no memory.
I loaded the fnt file with lualoader, I would love to know how to do this in esplorer (my main tool)

Code: Select allmod = { MOD_NAME = "oledilan"}
mod.dc = 3

mod.oled_gpio = {[0]=3,[2]=4,[4]=2,[5]=1,[12]=6,[13]=7,[14]=5}
mod.oled_id = 0
mod.oled_sda = mod.oled_gpio[0]
mod.oled_scl = mod.oled_gpio[2]
mod.oled_addr = 0x3C

mod.spi = 'true'

function mod.initSPI(dc_n)
     print("init SPI")
     dc = dc_n
     spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
     gpio.mode(dc, gpio.OUTPUT)


function mod.initI2C(sda_n, scl_n)
     print("init i2c")
     spi= 'false'
     oled_sda = mod.oled_gpio[sda_n]
     oled_scl = mod.oled_gpio[scl_n]
     i2c.setup(mod.oled_id, mod.oled_sda, mod.oled_scl, i2c.SLOW)

function mod.write_reg(dev_addr, reg_addr, reg_val)
     i2c.address(mod.oled_id, dev_addr, i2c.TRANSMITTER)
     i2c.write(mod.oled_id, reg_addr)
     i2c.write(mod.oled_id, reg_val)

function mod.command(...)
     if (spi == 'true') then
          gpio.write(dc, gpio.LOW)
          spi.send(1, arg)
         for i,v in ipairs(arg) do
           mod.write_reg(mod.oled_addr, 0, v)
         --mod.write_reg(mod.oled_addr, 0, arg)

function mod.on()


function mod.invert(state)
      mod.command(state == 1 and 0xA7 or 0xA6)

function mod.set_pos(x, y)
     mod.command(0xB0+y,, 0xf0) / 16 + 16,, 0x0e) + 1)

     --print("data", unpack(arg))
     if (spi == 'true') then
          gpio.write(dc, gpio.HIGH)
          spi.send(1, arg)
          print('write i2c')
          --for ic=0,4 do
          --     write_reg(oled_addr, 0x40, ascii[char][ic])
          --     tmr.wdclr()
         -- end

flashMod(mod) --everything before this is a flash function, everything after it is an in-memory public function"font6x8.fnt")
local font6x8 =

local function write(str, x, y)
     for i=1,#str do
          set_pos(x, y)
          local start = (string.byte(str,i) - 0x20)*6
          x = x + 6
          if x > 122 then x = 0; y = y + 1 end

return flashMod(mod)

Code: Select allprint("start", node.heap())
config = flashMod("oledilan")
print("after", node.heap())

Code: Select alltmr.alarm(0,1000,0,function()
     print("ready for action")