This question is as in the title, and pretty much that's it.
The firmware certainly knows what it carries inside. Here's the NodeMCU's "welcome" info:
NodeMCU ESP32 built on nodemcu-build.com provided by frightanic.com
branch: dev-esp32
commit: fb12af06e7e01f699d68496b80dae481e355adb7
SSL: false
modules: adc,can,dac,file,gpio,i2c,ledc,net,node,ow,sigma_delta,spi,time,tmr,touch,uart,wifi
build 2021-02-01-23-53-37 powered by Lua 5.1.4 on ESP-IDF v3.3-beta1-1391-g9e70825d1 on SDK IDF
lua: cannot open init.lua
>
I'd be more than happy to just get that comma-separated 'modules' string.
Since built-in modules are typically available under their names, as global variables, it is somewhat-similar to "how to list all global variables" in Lua, as I'd expect, everyone uses this on the normal Lua to inspect everything, including built-ins like math
. Yet, it isn't the same here. I've checked.
Listing globals from _G doesn't reveal existence of variables like tmr
or uart
.
> =tmr
romtable: 0x3f406e30
> =uart
romtable: 0x3f40acc8
> for k,v in pairs(_G) do print(k.." : "..tostring(v)) end
module : function: 0x3ffc2fa0
require : function: 0x3ffc2fd4
pairs : function: 0x3ffba950
newproxy : function: 0x3ffc90b4
package : table: 0x3ffba8fc
_G : table: 0x3ffc29c0
_VERSION : Lua 5.1
ipairs : function: 0x3ffba888
> for k,v in pairs(package.preload) do print(k.." : "..tostring(v)) end
((nothing!))
> for k,v in pairs(package.loaded) do print(k.." : "..tostring(v)) end
package
_G
As you can see, tmr
and uart
names are recognized, however, they are not listed as the contents of _G
.
Interestingly, even the math
is was not listed as in _G, even though it's clearly available:
> =math
romtable: 0x3f420ef0
> =_G.math
romtable: 0x3f420ef0
> =math.PI
nil
> =math.pi
3.1415926535898
What made me think, ok, what about those tmr
and uart
? Yup, the same:
> =_G.tmr
romtable: 0x3f406e30
> =_G.uart
romtable: 0x3f40acc8
and here we have it. They aren't listed in the contents of _G, and yet, they are available.
I'm not an expert in Lua nor NodeMCU, I may have missed something, but digging through the docs, trying out various Lua runtime inspection methods, I just can't figure out if/how to list them from _G.
I have a feeling that the _G has two separate meta-methods, one for listing, one for accessing/getting, and that only the latter one is patched up by the firmware to actually provide the modules-by-name, while the former isn't patched to list them, but that's just a guess.
As a side note, I got stuck on that on NodeMCU on ESP32, the dev-esp32
version (as available on https://nodemcu-build.com/), but as I'm wrinting this I tried the same on ESP8288, and the result is the same: math, tmr, uart are available directly, are available via _G, but aren't listed when inspecting _G's contents.
As a side note#2, after hours of searching I've found this video 'ESP8266 NodeMCU - How to know NodeMCU firmware Module info?
', that presents a "NodeMCU_firmware_info.lua", also called "AEW_NodeMCU_info.lua" (probably branding issue), which effectively simply contains a list of name-variable pairs and iterates over all hardcoded references to various modules, trying out each one for a nil
value..
Yeah, I know that will work. And that's exactly what I want to avoid. I'd like to read-out the built-in information without having to hardcode or bruteforce the names!
EDIT: as suggested by koyaanisqatsi, I checked _G's metatable and __index, and it turned out to be romtable
. Here's a dump:
function printtable(t) for k,v in pairs(t) do print(k.." : "..tostring(v)) end end
> printtable(getmetatable(_G))
__index : romtable: 0x3f4218b8
> printtable(getmetatable(_G)['__index'])
assert : lightfunction: 0x40156de8
collectgarbage : lightfunction: 0x40156be8
dofile : lightfunction: 0x40156bac
error : lightfunction: 0x40156b60
gcinfo : lightfunction: 0x40156b44
getfenv : lightfunction: 0x40156b14
getmetatable : lightfunction: 0x40156e8c
loadfile : lightfunction: 0x401570f4
load : lightfunction: 0x40156da4
loadstring : lightfunction: 0x40157120
next : lightfunction: 0x40156aec
pcall : lightfunction: 0x40156600
print : lightfunction: 0x40156a44
rawequal : lightfunction: 0x40156a1c
rawget : lightfunction: 0x401569f8
rawset : lightfunction: 0x4015694c
select : lightfunction: 0x401568f4
setfenv : lightfunction: 0x40156874
setmetatable : lightfunction: 0x4015677c
tonumber : lightfunction: 0x401566e0
tostring : lightfunction: 0x40156cfc
type : lightfunction: 0x401566bc
unpack : lightfunction: 0x40156638
xpcall : lightfunction: 0x401565bc
__metatable : romtable: 0x3f421b28
So, at least some of the built-in functions showed up finally, but sadly, neither of the modules, not even standard math
or debug
.
EDIT: I also checked how does that look like on on of my ESP8266's.
boot msg:
branch: release
commit: 64bbf006898109b936fcc09478cbae9d099885a8
release: 3.0-master_20200910
release DTS: 202009090323
SSL: false
build type: float
LFS: 0x40000 bytes total capacity
modules: adc,bit,cron,encoder,file,gpio,gpio_pulse,i2c,net,node,ow,pwm2,rtctime,sigma_delta,sntp,softuart,spi,tmr,wifi
build 2020-10-10 21:38 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
and _G's metatable:
printtable(getmetatable(_G)['__index'])
string : table: 0x402710e0
table : table: 0x402704cc
debug : table: 0x402719b0
coroutine : table: 0x40271694
math : table: 0x40270d04
ROM : table: 0x3ffef580
assert : function: 0x402424cc
......
......
net : table: 0x40274e9c
sntp : table: 0x40275268
bit : table: 0x40275398
adc : table: 0x40275494
gpio : table: 0x402756e4
tmr : table: 0x40275880
ow : table: 0x40275b04
softuart : table: 0x40275cd8
cron : table: 0x40275e2c
gpiopulse : table: 0x40276120
so in fact, the build-in modules DO show up here. Now, it's a puzzle, why they don't on ESP32?