Змінні та константи системного оточення, які можливо знайти у пам’яті NodeMCU на рівні Lua
Lua NodeMCU

Змінні та константи системного оточення, які можливо знайти у пам’яті NodeMCU на рівні Lua

Для того, щоб краще зрозуміти, як влаштоване системне оточення змінних і констант NodeMCU, варто хоча б раз на них поглянути.

Кожен C-модуль, доданий до складу прошивки може утворювати свої структури з посилань на функції та їх методи, константи та дані у тимчасових змінних. А отже, з цієї точки зору, також корисно подивитися, що є під капотом. Ми впевнені, що кожен знайде для себе щось нове і корисне.

Модулів у прошивці багато, а тому ми не будемо наводити повний перелік даних, а візьмемо лише деякі “системні” модулі.

Взявшись за вивід всього того, що є у пам’яті прошивки NodeMCU, ми не очікували, що там зберігається так багато різноманітних даних.

У нашому випадку, маємо наступну версію прошивки:

Цикл виводу даних

Найпростіший варіант, як вивести деякі з наявних даних у консоль, це запустити цикл, що роздруковує вміст глобальної змінної оточення _G:

Команда у консолі: for k, v in pairs(_G) do print(k, v) end

У відповідь отримаємо приблизно такі дані:

Але, якщо вивести на екран дані, що розташовано на рівень глибше:

Команда у консолі: for k, v in pairs(_G.__index) do print(k, v) end

вже отримаємо величезну купу цікавої інформації:

stringtable 0x4029eab4
tabletable 0x4029deb4
debugtable 0x4029f380
coroutinetable 0x4029f068
mathtable 0x4029e6d8
ROMtable 0x3ffef77c
assertfunction 0x40246bbc
collectgarbagefunction 0x40246920
dofilefunction 0x402468c0
errorfunction 0x40246870
gcinfofunction 0x40246848
getfenvfunction 0x4024680c
getmetatablefunction 0x40246c88
loadfilefunction 0x40246f80
loadfunction 0x40246b5c
loadstringfunction 0x40246fb8
nextfunction 0x402467d4
pcallfunction 0x402461b4
printfunction 0x4024672c
rawequalfunction 0x402466e8
rawgetfunction 0x402466b4
rawsetfunction 0x4024667c
selectfunction 0x40246594
setfenvfunction 0x40246508
setmetatablefunction 0x402463d4
tonumberfunction 0x402462d0
tostringfunction 0x40246a94
typefunction 0x4024629c
unpack function 0x402461fc
xpcallfunction 0x40246164
tlstable 0x4029fff4
rtctimetable 0x402a0258
uarttable 0x402a047c
i2ctable 0x402a0624
sjsontable 0x402a0804
wpstable 0x402a09a0
nodetable 0x402a1298
bme280table 0x402a158c
pipetable 0x402a162c
filetable 0x402a1a54
wifitable 0x402a274c
nettable 0x402a2e20
sntptable 0x402a31ec
adctable 0x402a32e8
gpiotable 0x402a3528
tmrtable 0x402a36c4
ws2812table 0x402a3a2c
httptable 0x402a3be4
mdnstable 0x402a3c74
softuarttable 0x402a3e48
crontable 0x402a3fa4

Зверніть увагу, що більшість назв збігається з назвами C-модулів у прошивці.

Та й це ще не все. Якщо рекурсивно вивести на екран абсолютно весь вміст змінної _G, то ми отримаємо 420 рядків за 21 ітерацію.

Але звісно, як ми вже казали, у складі цієї прошивки, багато додаткових C-модулів, як от adc, bme280, cron, file, gpio, http, i2c, mdns, net, node, rtctime, sjson, sntp, softuart, tmr, uart, wifi, wps, ws2812, tls

Все, що ми самостійно підключили генеруючи прошивку на сайті nodemcu-build.com, вважаємо додатковими модулями.

Крім того, що додаткових модулів дуже багато, призначення та їх методи відносно добре описано у документації на прошивку ось тут:

https://nodemcu.readthedocs.io/en/release/

І тому ми не будемо на них зупинятися.

Якщо дані про згадані додаткові компоненти відкинути, то отримаємо ось такий набір змінних і констант системного оточення _G, які описують інтерфейси доступу до вбудованих (які включено до прошивки за замовчуванням) функцій та їх даних:

_Gtable
_G.modulefunction
_G.pairsfunction
_G.__indextable
_G.__index.stringtable
_G.__index.string.__indextable
_G.__index.string.__modfunction
_G.__index.string.bytefunction
_G.__index.string.charfunction
_G.__index.string.dumpfunction
_G.__index.string.findfunction
_G.__index.string.formatfunction
_G.__index.string.gfindfunction
_G.__index.string.gmatchfunction
_G.__index.string.gsubfunction
_G.__index.string.lenfunction
_G.__index.string.lowerfunction
_G.__index.string.matchfunction
_G.__index.string.repfunction
_G.__index.string.reversefunction
_G.__index.string.subfunction
_G.__index.string.upperfunction
_G.__index.tabletable
_G.__index.table.concatfunction
_G.__index.table.foreachfunction
_G.__index.table.foreachifunction
_G.__index.table.getnfunction
_G.__index.table.maxnfunction
_G.__index.table.insertfunction
_G.__index.table.removefunction
_G.__index.table.setnfunction
_G.__index.table.sortfunction
_G.__index.debugtable
_G.__index.debug.getregistryfunction
_G.__index.debug.getstringsfunction
_G.__index.debug.tracebackfunction
_G.__index.coroutinetable
_G.__index.coroutine.createfunction
_G.__index.coroutine.resumefunction
_G.__index.coroutine.runningfunction
_G.__index.coroutine.statusfunction
_G.__index.coroutine.wrapfunction
_G.__index.coroutine.yieldfunction
_G.__index.mathtable
_G.__index.math.absfunction
_G.__index.math.ceilfunction
_G.__index.math.floorfunction
_G.__index.math.maxfunction
_G.__index.math.minfunction
_G.__index.math.powfunction
_G.__index.math.randomfunction
_G.__index.math.randomseedfunction
_G.__index.math.sqrtfunction
_G.__index.math.pi3.1415926535898
_G.__index.math.hugeinf
_G.__index.ROMtable
_G.__index.assertfunction
_G.__index.collectgarbagefunction
_G.__index.dofilefunction
_G.__index.errorfunction
_G.__index.gcinfofunction
_G.__index.getfenvfunction
_G.__index.getmetatablefunction
_G.__index.loadfilefunction
_G.__index.loadfunction
_G.__index.loadstringfunction
_G.__index.nextfunction
_G.__index.pcallfunction
_G.__index.printfunction
_G.__index.rawequalfunction
_G.__index.rawgetfunction
_G.__index.rawsetfunction
_G.__index.selectfunction
_G.__index.setfenvfunction
_G.__index.setmetatablefunction
_G.__index.tonumberfunction
_G.__index.tostringfunction
_G.__index.typefunction
_G.__index.unpackfunction
_G.__index.xpcallfunction
_G.__index.pipetable
_G.__index.pipe.createfunction
_G.packagetable
_G.package.preloadtable
_G.package.loadlibfunction
_G.package.path?.lc;?.lua
_G.package.loaderstable
_G.package.loaders.1function
_G.package.loaders.2function
_G.package.loaders.3function
_G.package.loaders.4function
_G.package.cpath
_G.package.loadedtable
_G.package.loaded.packagetable
_G.package.config/;?!-
_G.package.seeallfunction
_G._Gtable
_G._VERSIONLua 5.1
_G.ipairsfunction
_G.newproxyfunction
_G.requirefunction

Які ми можемо зробити відкриття, виходячи з цієї інформації? – Щонайменше, ми можемо бачити перелік вбудованих у прошивку C-модулів та їх методів, про які ми могли навіть не підозрювати і які ми можемо використовувати під час розробки на рівні Lua (а деякі з них, взагалі, являють собою частину мови Lua):

Примітка: звернуть увагу, що на ці модулі і їх методи немає документації прошивки NodeMCU, як на зовнішні C-модулі, але вони добре описані у NodeMCU Reference Manual, тобто у документації на мову Lua безпосередньо: https://nodemcu.readthedocs.io/en/release/nodemcu-lrm/

Модуль string
_G.__index.stringtable
_G.__index.string.__indextable
_G.__index.string.__modfunction
_G.__index.string.bytefunction
_G.__index.string.charfunction
_G.__index.string.dumpfunction
_G.__index.string.findfunction
_G.__index.string.formatfunction
_G.__index.string.gfindfunction
_G.__index.string.gmatchfunction
_G.__index.string.gsubfunction
_G.__index.string.lenfunction
_G.__index.string.lowerfunction
_G.__index.string.matchfunction
_G.__index.string.repfunction
_G.__index.string.reversefunction
_G.__index.string.subfunction
_G.__index.string.upperfunction
Модуль table
_G.__index.tabletable
_G.__index.table.concatfunction
_G.__index.table.foreachfunction
_G.__index.table.foreachifunction
_G.__index.table.getnfunction
_G.__index.table.maxnfunction
_G.__index.table.insertfunction
_G.__index.table.removefunction
_G.__index.table.setnfunction
_G.__index.table.sortfunction
Модуль gebug
_G.__index.debugtable
_G.__index.debug.getregistryfunction
_G.__index.debug.getstringsfunction
_G.__index.debug.tracebackfunction
Модуль coroutine
_G.__index.coroutinetable
_G.__index.coroutine.createfunction
_G.__index.coroutine.resumefunction
_G.__index.coroutine.runningfunction
_G.__index.coroutine.statusfunction
_G.__index.coroutine.wrapfunction
_G.__index.coroutine.yieldfunction
Модуль math
_G.__index.mathtable
_G.__index.math.absfunction
_G.__index.math.ceilfunction
_G.__index.math.floorfunction
_G.__index.math.maxfunction
_G.__index.math.minfunction
_G.__index.math.powfunction
_G.__index.math.randomfunction
_G.__index.math.randomseedfunction
_G.__index.math.sqrtfunction
_G.__index.math.pi3.1415926535898
_G.__index.math.hugeinf
Модуль pipe
_G.__index.pipetable
_G.__index.pipe.createfunction
Інші, важливі методи, що ми щоденно застосовуємо
_G.modulefunction
_G.pairsfunction
_G.__index.assertfunction
_G.__index.collectgarbagefunction
_G.__index.dofilefunction
_G.__index.errorfunction
_G.__index.gcinfofunction
_G.__index.getfenvfunction
_G.__index.getmetatablefunction
_G.__index.loadfilefunction
_G.__index.loadfunction
_G.__index.loadstringfunction
_G.__index.nextfunction
_G.__index.pcallfunction
_G.__index.printfunction
_G.__index.rawequalfunction
_G.__index.rawgetfunction
_G.__index.rawsetfunction
_G.__index.selectfunction
_G.__index.setfenvfunction
_G.__index.setmetatablefunction
_G.__index.tonumberfunction
_G.__index.tostringfunction
_G.__index.typefunction
_G.__index.unpackfunction
_G.__index.xpcallfunction
_G.ipairsfunction
_G.newproxyfunction
_G.requirefunction
Модуль package
_G.packagetable
_G.package.preloadtable
_G.package.loadlibfunction
_G.package.path?.lc;?.lua
_G.package.loaderstable
_G.package.loaders.1function
_G.package.loaders.2function
_G.package.loaders.3function
_G.package.loaders.4function
_G.package.cpath
_G.package.loadedtable
_G.package.loaded.packagetable
_G.package.config/;?!-
_G.package.seeallfunction

Наприклад, візьмемо вбудований модуль математичних функцій math. Знайдене у системному оточенні, означає, що в даному модулі є методи і можемо їх застосовувати

math.abs(), 
math.ceil(), 
math.floor(), 
math.max(), 
math.min(), 
math.pow(), 
math.random(), 
math.randomseed(), 
math.sqrt().

Також маємо вектори посилання на значення для констант:

math.pi == 3.1415926535898

math.huge == inf -- тобто infinity, нескінченність

По аналогії, з системного оточення можливо виокремити й інші функції та використовувати у програмуванні мікроконтролера ESP8266 на рівні викликів у Lua.

Рекурсивний вивід даних

Щоб отримати більш повний перелік системного оточення радимо скористатися прикладом з офіційного набору файлів прошивки, що через обгортку в coroutine, дозволяє запустити рекурсивний вивід даних у консоль розробника.

Для цього знадобиться скачати і завантажити у контролер файл lua-модуля cohelper.lua:

https://github.com/nodemcu/nodemcu-firmware/blob/release/lua_modules/cohelper/cohelper.lua

Вміст файлу:

Повний приклад запуску рекурсії тут:

https://nodemcu.readthedocs.io/en/release/lua-modules/cohelper/#full-example

Вміст файлу:

Все що потрібно, щоб все запустити рекурсивний вивід даних системного оточення у консоль, у вас має бути два файли у контролері, на які вказано посилання. 

Наприклад так:

  • cohelper.lua
  • cohelper_full_example.lua, який сам викликає cohelper.lua через метод require.
  • запустити cohelper_full_example.lua через dofile().

Що ми знайшли для себе

Серед більшості відомих нам функцій Lua, таких як:

ми для себе знайшли кілька, з якими ми зовсім/мало (не)працювали, або про існування яких забули з якихось причин:

І тому, маємо в планах надолужити: розібратися що це за методи і спробувати включити їх можливості у щоденне застосування, там, де це буде доцільним.

Ось і все, що ми хотіли розповісти за цією темою на сьогодні.

Бажаємо успіхів!