ESP-8266/ESP32 NodeMCU Lua: азы программирования.

Тема в разделе "ESP8266, ESP32", создана пользователем ИгорьК, 25 июл 2017.

  1. serg3295

    serg3295 Гик

    Странно. У меня работает без скобок. Вот такой init.lua

    Код (C++):
    if node.LFS.get("_init") == nil then
        node.LFS.reload("lfs.img")
    end

    local initTimer = tmr.create()
    initTimer:register(1000, tmr.ALARM_SINGLE,
        function(t)
            if pcall(node.LFS.get("_init")) then node.LFS.prog() end
            t = nil
        end)
    initTimer:start()
     
    Правда я прошил 3.0.0 релиз, а не мастер. Может в этом дело. Кстати, ещё можно поправить _init, который в LFS. В том, который в примере не работает механизм приоритета поиска модулей. То есть если загрузить в spiffs скажем файл prog.lua, то он будет исполнятся. А если стереть, то выполнится тот prog, который в LFS. Так вот, чтоб это работало надо подправить _init. Вот так примерно:
    Код (C++):
    local lf, df, file_exists = loadfile, dofile, file.exists
    G.loadfile = function(n)
      local mod = n:match("(.*)%.(l[uc]a?)");
      if file_exists(n) then return lf(n) else return (index(mod) or lf(n)) end
    end

    G.dofile = function(n)
      local mod = n:match("(.*)%.l[uc]a?");
      local fn  = index(mod)
      if file_exists(n) then return df(n)
      elseif fn then return fn()
      else return df(n) end
    end
     
    А загрузку и сборку в LFS настроил себе в VSCode. Теперь всё делается несколькими нажатиями клавиш. Достаточно быстро.
     
    swc, ИгорьК и ioex нравится это.
  2. ioex

    ioex Нерд

    Аналогично, глобальная таблица и загрузка по необходимости и выгрузка, если без надобности. Вообще я многие подходы позаимствовал у Вас в этой теме. Но этого бывает не достаточно, всё зависит от задачи.

    Как говорится "Совершенству нет предела" или "Хорошая мысля приходит опосля". Когда девайс готов и запущен в работу, всегда приходят мысли, что вот здесь можно было сделать получше или по другому. А потом ползать с ноутом под потолком удовольствие так себе. Ну и второй вариант, у меня пару ESP работают в гараже, (wifi,vpn домой). Там вариант с удалённой загрузкой ещё более актуален, который, кстати, тоже находится в LFS ))

    в итоге в init.lua получилось что-то вроде того
    Код (C++):
    node.LFS.get('_init')()

    if rtcmem.read32(0) == 501 then
        print("Start Server!")
        rtcmem.write32(0, 0)
        node.LFS.get('http')()
    else
        status,err = pcall(function()
            if not file.exists('to_lfs') and file.exists('LFS.img') then
                to_lfs = file.open("to_lfs", "w")
                to_lfs:close()
                to_lfs = nil
                print('Reloading LFS.img')
                node.LFS.reload('LFS.img')
            else
                if file.exists('to_lfs') then file.remove("to_lfs") end
                if file.exists('LFS.img') then file.remove("LFS.img") end
            end
        end)
        tmr.create():alarm(5000, 0,  function()
            if status then
                for k,v in pairs(node.LFS.list()) do print(k,v) end
                node.LFS.get('setglobals')()
            else
                print("error:", err)
                print("Start HTTP")
                rtcmem.write32(0, 501)
                node.restart()
            end
            status,err = nil,nil
        end)
    end
     
     
    Последнее редактирование: 3 окт 2020
    swc нравится это.
  3. ioex

    ioex Нерд

    я сначала засомневался в себе, но потом пошёл проверять.
    в образе LFS у нас файл hello.lua и в нём функция hello()
    Код (C++):
    function hello()
        print('Hello from LFS')
    end
     
    конструкция типа:
    Код (C++):
    node.LFS.get('hello')
    hello()
    выдаёт ошибку
    в то же время при:
    Код (C++):
    node.LFS.get('hello')()
    hello()
    всё ок, "Hello from LFS"
    Не знаю, может я такой везунчик, либо разница в версиях. У меня прошит "build 2020-10-01 14:47 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)"

    А что за node.LFS.prog() ?
    В доках не упоминается.
     
    swc нравится это.
  4. serg3295

    serg3295 Гик

    У меня собрано из исходников с git. 3.0-release_20200910
    пишет - powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e). Дата, естественно, компиляции

    prog - это я так свой модуль обозвал. Можно main, или всё равно как. Эквивалентно node.LFS.get("prog")

    Из документации:
    Note that unused node.LFS properties map onto the equialent get() call so for example: node.LFS.mySub1 is a synonym for node.LFS.get('mySub1').

    P.S. в _init.lua надо ещё строчку подправить
    localindex = node.LFS.get --node.flashindex

    чтобы проверить окончательно - вот мой _init
    Код (C++):
    local index = node.LFS.get --node.flashindex
    local G=_ENV or getfenv()
    local lfs_t
    if _VERSION == 'Lua 5.1' then
        lfs_t = {
        __index = function(_, name)
            local fn_ut, ba, ma, size, modules = index(name)
            if not ba then
              return fn_ut
            elseif name == '_time' then
              return fn_ut
            elseif name == '_config' then
              local fs_ma, fs_size = file.fscfg()
              return {lfs_base = ba, lfs_mapped = ma, lfs_size = size,
                      fs_mapped = fs_ma, fs_size = fs_size}
            elseif name == '_list' then
              return modules
            else
              return nil
            end
          end,

        __newindex = function(_, name, value) -- luacheck: no unused
            error("LFS is readonly. Invalid write to LFS." .. name, 2)
          end,
        }

        setmetatable(lfs_t,lfs_t)
        G.module       = nil    -- disable Lua 5.0 style modules to save RAM
        package.seeall = nil
    else
        lfs_t = node.LFS
    end
    G.LFS = lfs_t

    --[[-------------------------------------------------------------------------------
      The second section adds the LFS to the require searchlist, so that you can
      require a Lua module 'jean' in the LFS by simply doing require "jean". However
      note that this is at the search entry following the FS searcher, so if you also
      have jean.lc or jean.lua in SPIFFS, then this SPIFFS version will get loaded into
      RAM instead of using. (Useful, for development).
      See docs/en/lfs.md and the 'loaders' array in app/lua/loadlib.c for more details.
    ---------------------------------------------------------------------------------]]

    package.loaders[3] = function(module) -- loader_flash
      return lfs_t[module]
    end

    --[[-------------------------------------------------------------------------------
      These replaces the builtins loadfile & dofile with ones which preferentially
      loads the corresponding module from LFS if present.  Flipping the search order
      is an exercise left to the reader.-
    ---------------------------------------------------------------------------------]]
    --[[
    local lf, df = loadfile, dofile
    G.loadfile = function(n)
      local mod, ext = n:match("(.*)%.(l[uc]a?)");
      local fn, ba   = index(mod)
      if ba or (ext ~= 'lc' and ext ~= 'lua') then return lf(n) else return fn end
    end

    G.dofile = function(n)
      local mod, ext = n:match("(.*)%.(l[uc]a?)");
      local fn, ba   = index(mod)
      if ba or (ext ~= 'lc' and ext ~= 'lua') then return df(n) else return fn() end
    end

    --]]

    local lf, df, file_exists = loadfile, dofile, file.exists
    G.loadfile = function(n)
      local mod = n:match("(.*)%.(l[uc]a?)");
      if file_exists(n) then return lf(n) else return (index(mod) or lf(n)) end
    end

    G.dofile = function(n)
      local mod = n:match("(.*)%.l[uc]a?");
      local fn  = index(mod)
      if file_exists(n) then return df(n)
      elseif fn then return fn()
      else return df(n) end
    end
     
     
    Последнее редактирование: 3 окт 2020
    swc и ioex нравится это.
  5. ioex

    ioex Нерд

    хах, полез я тыкаться как слепой котёнок, проверять функционал на работоспособность ))
    Код (C++):
    function hello()
        print('hello from lfs')
    end
    hello()
    node.LFS.get('hello') -- не работает
    node.LFS.get('hello')() -- работает
    node.LFS.hello() -- работает

    Результат один вне зависимости какой _init.lua и подгружен ли он вообще.

    судя по всему эта фраза из документации не совсем соответствует действительности или я чего-то не понимаю.
     
    swc нравится это.
  6. serg3295

    serg3295 Гик

    Проверил на прошивке собранной с сайта
    release: 3.0-master_20200910
    release DTS: 202009090323
    Всё работает.
    Попробуйте сделать следующие вещи.
    1. перепрошиться со стиранием flash (похоже, этот _init где-то глубоко зарылся в LFS и не стирается. У меня тоже без _init в LFS выполнялся как будто бы старый _init был
    2. переименуйте функцию, или модуль. А то они у вас оба hello. Тут трудно искать кого вызываешь. Пусть главный модуль будет prog.lua
    3. сделайте отдельный файл pr.lua с объявлением функции hello и вызывайте его из prog через dofile('pr.lua')
    Код (C++):
    -- file pr.lua
    function hello()
        print('print from LFS')
    end

    -- file prog.lua
    dofile('pr.lua')
    hello()

     
    4. положите в spiffs init.lua и загрузите LFS
    5. после ресета должно напечатать "print from LFS"
    6. если заработало, то в файле pr.lua замените строку на print from spiffs. Этот файл с этим же именем pr.lua положите в spiffs
    7. после ресета должно напечатать print from spiffs
    8. переименуйте pr.lua в spiffs на что-нибудь
    9. после ресета должно напечатать print from LFS

    то есть можно отлаживать файл на spiffs, а когда отлажен уже запихивать в LFS. Как и рекомендует разработчик :)
     
    swc нравится это.
  7. ИгорьК

    ИгорьК Гуру

    Занес в шапку ссылку на дополнение по LFS.

    "node.LFS.mySub1 is a synonym for node.LFS.get('mySub1')"

    Что есть конструкция типа бла.бла.бла(node.LFS.mySub1)? Это ссылка.

    Документация выше говорит, что вызов функции node.LFS.get('mySub1') есть синоним ссылки.

    Документация выше говорит, что ссылка node.LFS.mySub1 есть синоним вызова функции node.LFS.get('mySub1') . В данном случае порядок сказанного имеет значение.

    Получается, здесь имеется в виду, что этот результат вызова есть та самая ссылка.

    UPD. Следовательно, поскольку node.LFS.get('mySub1') есть функция, которая получает ссылку, то и синоним этого node.LFS.mySub1 есть не просто ссылка, а тоже функция, дающая на выходе ссылку.

    Дальше все просто - добавляем () и функция по ссылке вызывается.

    Таким образом,
    node.LFS.get('hello')() -- работает
    node.LFS.hello() -- работает
    а
    node.LFS.get('hello') работать не должен, ибо это лишь ссылка.

    Попробуйте следующее:
    Код (Lua):
    var = node.LFS.get('hello')
    var()
    Есть вероятность что запустится.

    Или так:
    Код (Lua):
    print(node.LFS.get('hello'), node.LFS.hello)
    Интересно что будет. Полагаю, будут напечатаны две одинаковые цифры.
     
    Последнее редактирование: 6 окт 2020
    swc и serg3295 нравится это.
  8. serg3295

    serg3295 Гик

    Да, так всё верно.
    Код (C++):
    ***********>>>>>> restart

    > node.LFS.get('hello')
    > hello()
    Lua error:     stdin:1: attempt to call global 'hello' (a nil value)
    stack traceback:
        stdin:1: in main chunk
        [C]: ?
        [C]: ?
    >
    > node.LFS.get('hello')()
    > hello()
    Hello from LFS
    >

    ***************>>>>>> restart

    > var = node.LFS.get('hello')
    > var()
    > hello()
    Hello from LFS
    >
     
    С функциями как-то запутано. Видно в _init их переколбашивает
    Код (C++):
    NodeMCU 3.0.0.0 built on nodemcu-build.com provided by frightanic.com
        branch: release
        commit: 64bbf006898109b936fcc09478cbae9d099885a8
        release: 3.0-master_20200910
        release DTS: 202009090323
        SSL: false
        build type: float
        LFS: 0x10000 bytes total capacity
        modules: bit,cron,file,gpio,mqtt,net,node,ow,rtcmem,rtctime,sjson,sntp,tmr,uart,wifi
    build 2020-09-29 06:46 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
    cannot open init.lua:
    > print(uart.setup(0, 115200, 8, 0, 1, 1 ))
    115200

    { lfs_addr = 0x07c000, lfs_size = 0x010000, spiffs_addr = 0x100000, spiffs_size = 0x010000 }

    > print(node.LFS.get('hello'), node.LFS.hello)
    function: 0x3fff0640    function: 0x3fff06d0

        =========== _G table: ===========
    module    function: 0x4023d528
    pairs    function: 0x3fff0380
    __index    table: 0x3ffef470
    package    table: 0x3fff0950
    _G    table: 0x3fff0350
    _VERSION    Lua 5.1
    ipairs    function: 0x3fff05e0
    newproxy    function: 0x3fff0760
    require    function: 0x4023d378

    ===== package.loaded table: =====
    package    table: 0x3fff0950
    =================================
    Reg: 1    Heap: 43120
    =================================

    > hello()
    Lua error:     stdin:1: attempt to call global 'hello' (a nil value)
    stack traceback:
        stdin:1: in main chunk
        [C]: ?
        [C]: ?

    > node.LFS.hello()
    > hello()
    Hello from LFS

    =========== _G table: ===========
    module    function: 0x4023d528
    pairs    function: 0x3fff0380
    __index    table: 0x3ffef470
    package    table: 0x3fff0950
    _G    table: 0x3fff0350
    _VERSION    Lua 5.1
    ipairs    function: 0x3fff05e0
    hello    function: 0x3fff0550
    newproxy    function: 0x3fff0760
    require    function: 0x4023d378

    ===== package.loaded table: =====
    package    table: 0x3fff0950
    =================================
    Reg: 1    Heap: 43128
    =================================

    > print(node.LFS.get('hello'), node.LFS.hello)
    function: 0x3fff0578    function: 0x3fff05a0
    >
     
    swc и ИгорьК нравится это.
  9. ИгорьК

    ИгорьК Гуру

    Все с ними нормально. Это я ошибся.
    Да, адреса получаются (и должны быть) не одинаковыми и вот почему.

    Видимо, каждый вызов любой из этих конструкций кладет в регистр собственную ссылку на модуль LFS, кстати, тем самым забивая его (регистр).

    То есть, синтаксически, вызовы равноценны, но каждый вызов делает именно новую запись, а не дублирует старую. И это, видимо, обосновано. Вы можете сделать несколько обращений к модулю, например, с разным набором аргументов (если он такое поддерживает). Ну и вообще - кто полагал что мы тут придумаем :)

    Так что для проверки выполните:
    Код (Lua):
     print(node.LFS.get('hello'), node.LFS.get('hello') , node.LFS.hello, node.LFS.hello)
    Должно получиться 4 разных цифры :) А если две пары - у меня мыслей нет.
     
    swc и serg3295 нравится это.
  10. serg3295

    serg3295 Гик

    Код (C++):
    > print(node.LFS.get('hello'), node.LFS.get('hello') , node.LFS.hello, node.LFS.hello)
    function: 0x3fff0640    function: 0x3fff06d0    function: 0x3fff08d0    function: 0x3fff08f8
    > hello()
    Lua error:     stdin:1: attempt to call global 'hello' (a nil value)
    stack traceback:
        stdin:1: in main chunk
        [C]: ?
        [C]: ?
    > node.LFS.hello()
    > hello()
    Hello from LFS

    =========== _G table: ===========
    module    function: 0x4023d528
    pairs    function: 0x3fff0380
    __index    table: 0x3ffef470
    package    table: 0x3fff0950
    _G    table: 0x3fff0350
    _VERSION    Lua 5.1
    ipairs    function: 0x3fff05e0
    hello    function: 0x3fff0640
    newproxy    function: 0x3fff0760
    require    function: 0x4023d378

    ===== package.loaded table: =====
    package    table: 0x3fff0950
    =================================
    Reg: 1    Heap: 42584
    =================================
     
    Главное, работает как ожидалось. А механизмы авторы там могут и поменять.
    Они вообще, с переходом на LUA5.3 по умолчанию, похоже много чего наменяют.
     
    swc и ИгорьК нравится это.
  11. ИгорьК

    ИгорьК Гуру

    Ну, все выяснилось :) Будем ждать 5.3
     
    swc нравится это.
  12. serg3295

    serg3295 Гик

    Visual Studio Code и Lua

    В процессе изучения Lua в связке с NodeMCU через некоторое время мне захотелось автоматизировать некоторые операции по работе с ESP через COM порт, и получить дополнительные удобства при набирании и редактировании кода, которые обычно предоставляют большие программные IDE.
    Для решения данных задач я перешёл на VSCode и настроил его для работы с Lua и ESP путём написания нескольких команд и скриптов. Возможно, профессиональным программистам моё дальнейшее описание будет не очень интересно, так как для них всё это очевидно, но для начинающих типа меня, может оказаться полезным.
    Итак. Многие пользуются notepad++, так как он очень быстрый и многофункциональный за счёт огромного количества плагинов. Однако, с появлением VSCode, появилась альтернатива. Он достаточно быстр, в отличии от своего старшего собрата VisualStudio, и количество расширений, предоставляемых в Marketplace, расширяет его функционал очень существенно.
    Для облегчения перехода с других редакторов есть возможность установить схему клавиш. Для notepad++, для vim и ряда других.
    Для комфортной работы просто с Lua в VSCode достаточно установить следующие расширения:

    Lua Language Server coded by Lua автор sumneko

    Это расширение выполняет проверку и подсветку синтаксиса, автозавершение кода (когда ещё плохо знаешь конструкции языка, очень помогает), поиск и переход по определениям, показывает необъявленные переменные и т.д.

    После установки через «Расширения» достаточно настроить, нажав на шестерёнку, несколько параметров расширения. Причём лучше менять на вкладке Рабочая область, а значения на вкладке Пользователь оставить по дефолту.

    Lua>Diagnostics: Globals

    Написать туда gpio, tmr, file и остальные, используемые вами, модули nodemcu

    Runtime:Version

    5.1 (с переходом вскоре nodemcu на 5.3 можно будет оставлять по дефолту)

    По желанию, запретить lowercase-global. А то он считает, что все глобальные переменные должны быть большими буквами. Кто считает также – может параметр не менять.

    Второе расширение Lua Debug автор actboy168

    Это неплохой отладчик. Естественно, для работы непосредственно с nodeMCU в realtime он непригоден, но отлаживать кусочки логического кода, и тренироваться в изучении Lua он очень и очень мне помогает. ( Можно ещё поставить расширение CodeRunner, тогда удобно будет запускать код на PC)

    Параметров для настройки у него немного, у меня там везде utf8 и параметр Console установлен в internalConsole.

    Другие расширения Lua на Marketplace тоже предлагаются, но эти самые функциональные, на мой взгляд. К тому же они поддерживаются в активном состоянии обоими авторами.

    Из общих расширений, делающих работу удобной, можно отметить ProjectManager автора AlessandroFragnani. Вообще, раньше проекты в VSCode я открывал путём Файл –> Открыть папку. После установки ProjectManager достаточно щёлкнуть по названию проекта. Очень удобно, а то пока нужную папку найдёшь…
    Правда, один раз всё-таки придётся выполнить Файл –> Открыть папку. Затем сохранить проект, нажав слева на пиктограмму расширения ProjectManager.

    На этом стандартную установку и настройку VSCode с расширениями для Lua можно считать законченной. Уже можно комфортно работать.

    Теперь приступаем к автоматизации скриптами и командами.

    Продолжение →
     
    Последнее редактирование модератором: 12 окт 2020
    swc и ИгорьК нравится это.
  13. serg3295

    serg3295 Гик

    ← Предыдущее сообщение | Продолжение →

    Автоматизация


    Для упрощения загрузки файлов в ESP по COM порту и для сборки LFS, не выходя из VSCode, необходимо установить ряд программ.
    Первая - это утилита NodeMCUTool, выполняемая из командной строки

    https://github.com/AndiDittrich/NodeMCU-Tool

    NodeMCUTool позволяет выгружать через COM порт файлы LUA, или двоичные файлы в ESP8266/ESP32/NodeMCU по одному, или пачкой, выполняет ряд файловых операций, и главное, убирает при загрузке все комментарии и лишние пробелы, используя luamin. Это даёт возможность подробно комментировать код, не заботясь о размере загружаемого файла. По совместительству утилита работает терминалом, если надо. Устанавливается как global package через npm

    npm install nodemcu-tool -g

    Вторая – это кросс компилятор Lua luac.cross.exe

    Здесь стоит обратить внимание, что, если вы скачали кросс компилятор с git и он называется, например, lua.crossx64 floatLua51.exe, то его надо будет переименовать в luac.cross.exe. Для того, чтобы система нашла путь к этому компилятору, он должен присутствовать в переменных среды Windows. Самый простой способ этого добиться – установить Lua для windows и положить luac.cross.exe в c:\Program Files (x86)\Lua\5.1\
    Или туда, куда вы установили. Или руками прописать системную переменную с путём.

    Что будут делать команды автоматизации. Они все приведены в файле task.json.
    • Выгрузить текущий файл в ESP
    • LFS собрать, выгрузить и flashreload
    • Запустить текущий файл
    • Кросс компилятор
    • Файл скомпилировать, выгрузить, запустить
    • и другие.
    Реально я использую только несколько команд, остальные были написаны для экспериментов и отладки. Желающие могут их модифицировать, или стереть. Однако они не мешаются, так как наиболее часто используемые команды всплывают в меню выбора наверх. Ими и пользуемся.

    Теперь создадим проект в ProjectManager с именем hello, и он должен иметь следующую структуру:

    Папка hello
    файлы с программой. hello.lua
    подкаталоги:
    .vscode (обращаю внимание на точку. Имя не менять.)
    .output (обращаю внимание на точку. Имя не менять.)
    init (это имя подкаталога , в отличии от предыдущих двух, может быть любым)

    В .vscode лежат файлы настроек данного проекта и скрипты
    В .output кладутся *.lc, *.log, lfs.img (этот каталог обязателен для кросс компилятора и LFS, иначе скрипты не выполнятся как надо)
    Каталог init содержит файл init.lua. Он спрятан в подкаталог, чтобы его не зацепило при сборке LFS. Скрипт сборки LFS, в принципе, повторяет требования к bat файлу сборки, то есть, собираться будут файлы, находящиеся в верхнем каталоге (hello в нашем случае).

    Важно! Скрипты привязаны к иерархии каталогов от папки проекта. Папку проекта можно класть куда хочешь.

    Содержимое папки .vscode :
    launch.json – запуск дебаггера. В случае nodeMCU не актульно
    lfs.ps1 – скрипт сборки LFS. Там в переменной var уже написано под новый релиз. Если релиз старый – верните flashreload
    pack.ps1 – скрипт компилирует и выгружает в ESP. Файлы *.lc и *.log укладываются в .output. Там их и смотрим, если что не так.
    settings.json - туда заносятся локальные для проекта настройки от расширений.
    task.json – собственно команды.

    В командах везде сделан выбор СОМ порта для выгрузки. Учитывая способность windows назначать номера COM портов по своему усмотрению, я ввёл такую возможность.
    Если у вас по какой-то причине номера портов не меняются, то в строке команды вместо ${inputPORT} напишите --port=COMномер_вашего_порта (два дефиса спереди)

    Ещё можно в "default": "--port=COM4" прописать свой номер, тогда он будет всегда на самом верху и подсвечен для выбора.

    Вообще, эти игры с COM’ами влияют только на количество нажатий клавиши для подтверждения – один или два. Или ноль, если COM жёстко забит в строку.

    Как пользоваться.
    1. Надо встать мышью на файл в окошке редактирования. То есть, если вы хотите произвести операцию с файлом, то фокус должен быть на нём. Причём, не в проводнике слева, а в окне редактирования!!
    2. Убедимся, что закрыт COM порт, открытый Esplorer’ом на соседнем мониторе (если он, конечно у вас открыт, как у меня).
    3. Жмём Ctrl+Alt+T
    4. Предлагается выбрать задачу для запуска. Выберем, например, задачу "Выгрузить текущий файл в ESP".
    5. Предлагает выбрать COM порт (если в командной строке ${inputPORT})
    6. Файл, на котором мы стояли, улетает в ESP с индикацией процесса на встроенном терминале VSCode, открывшемся внизу окна. Когда всё выгрузилось, жмём пробел, или любую другую клавишу. Если надо выгрузить .lc файл, а он бинарный, то также выбираем в проводнике VSCode .lc файл, встаём на правое окно его редактирования и выгружаем. Предупреждение о том, что он не может отобразиться – игнорируем. Или, если хочется посмотреть – что там внутри, то установите расширение hexDump for VSCode.
    Если вы хотите просто скомпилировать файл, то, встав на него, жмёте “компиляция”. Результат – два файла. log и .lc будут в каталоге .output

    В случае с LFS надо встать на ЛЮБОЙ файл из каталога (где все программы наши лежат) и выбрать команду “LFS собрать, выгрузить и flashreload”. Все файлы скомпилируются, соберутся в LFS, и отправятся в ESP. Затем выполнится перезагрузка LFS на ESP и она рестартует.
    В отличии от других команд, окно терминала здесь надо закрывать нажатием на урну в командном меню терминала в правом верхнем его углу. Стучанием по пробелу он не закроется. Это связано с особенностью передачи параметров в nodemcu-tool.

    Пару слов про организацию (ну, как у меня сделано) каталогов и проектов для Lua.

    Каталог Dz для домотикз. Там на весь каталог одно workspace, следовательно, один каталог .vscode на все подпапки проектов.

    Каталог nodemcu. Там каждый проект в своей папке, и, следовательно, настройки для каждого проекта свои (папка .vscode в каждом проекте своя). Если сделать общий workspace на все проекты, то расширение lua server будет считать, что это всё общее. Тогда переменные, определённые в другом проекте с теми же именами, не будут подчёркиваться в текущем проекте как неопределённые.

    Каталог РС. Ну, это для экспериментов в среде компьютера.
    Вроде всё. Ещё раз повторюсь, я это настраивал для себя и идя по пути освоения Lua и nodemcu, постоянно читая эту тему. То есть это всё для начинающих. Возможно, достигнув просветления и, перейдя на следующий уровень, этот метод работы покажется чем-то странным и излишним.

    В аттаче zip с проектом hello и настройками.

    Забыл выложить рабочие файлы настроек для конфигурации debug и CodeRunner для запуска на PC.
    Здесь стоит обратить внимание, что Windows странно работает с UTF8 в терминале. Даже при установке галочки "Экспериментальное использование UTF8" в языковых настройках Windows при выводе возникают проблемы с русским языком. Если не класть эти файлы конфигурации в .vscode, то выводит в терминал по-русски. Для проверки выполните

    io.write("rus-русский текст")

    но тогда не работает ввод по
    a = io.read("*n")

    Если файлы конфигурации положить в .vscode, то можно будет вводить данные с терминала в интерактивном режиме, однако с русским текстом печалька. То есть выход - писать всё по английски. Победить мне это не удалось. Если кто знает как и расскажет - будет молодец.

    ← Предыдущее сообщение | Продолжение →
     

    Вложения:

    • hello.zip
      Размер файла:
      3,7 КБ
      Просмотров:
      199
    • .vscode.zip
      Размер файла:
      923 байт
      Просмотров:
      198
    Последнее редактирование модератором: 12 окт 2020
    swc и ИгорьК нравится это.
  14. ИгорьК

    ИгорьК Гуру

    В шапке.
     
    swc и serg3295 нравится это.
  15. serg3295

    serg3295 Гик

    ← Предыдущее сообщение | Продолжение →

    Автоматизация 2


    Для того, чтобы иметь возможность отвязаться от COM порта, и всё также работать в VSCode я написал ещё несколько команд. Теперь можно выгружать файлы по FTP и также собирать LFS и выгружать её по FTP. Соответственно, скорость выгрузки сильно увеличилась. Вариант HTTP_OTA я пока не придумал как прикрутить к VSCode.

    Модуль FTP в настоящее время работает только с LFS из-за своего большого размера. Хотя возможно в ближайшее время разработчики реализуют заявленный ими механизм работы ftp (в том числе) на spiffs. Обсуждение планов здесь

    А пока, просто загрузив минимальный набор файлов, получаем более быстрый (в отличии от COM’а) и удалённый (если надо) механизм загрузки на ESP интегрированный в VSCode. Также можно пользоваться TotalCommander’ом подконнектившись по ftp. Это, если нужен расширенный вариант файловых операций.
    ftpserver.lua включен в проект сразу и ftp сервер стартует, позволяя в дальнейшем загружать оставшиеся программы, или менять их по необходимости.

    Дополнительно к предыдущим добавились две команды “Выгрузить по FTP” и “buildLFS & FTP”. Требования к выполнению команд такие же, как были описаны ранее. Изменился только механизм доставки. Для реализации связи по FTP используется curl.exe, встроенный в Windows 10.

    В каталоге .vscode, кроме изменившегося файла tasks.json, появились ftp.ps1и ftp.txt. Править под себя нужно только ftp.txt, там всего две строчки. Логин и пароль на ftpserver должны быть такими же, как в строке кода в файле main.lua

    node.LFS.ftpserver():createServer("test","12345")

    ,где test– логин, а 12345 – пароль.

    При первоначальной загрузке в проекте должны быть init.lua на spiffs и собранная LFS с файлами main.lua, _init.lua и ftpserver.lua.

    После рестарта можно проверить, что сервер стартовал, набрав в терминале команду

    Curl.exe ftp://192.168.*.* --user test:12345 --ftp-pasv --disable-epsv –v

    В ответе будут слова про успешную аутентификацию и выведено содержание каталога.

    Самое неприятное во всём этом – это то, что пришлось для рестарта LFS приделывать жёсткий костыль в коде. Ввёл команду, которой нет в спецификации FTP. Изменил немного оригинальный ftpserver.lua. Строки 192, 245-248. Команда RST.
    Ну никак было не придумать метод удалённого сброса ESP при наличии только FTP при старте. Только если вспомогательный файл писать и вешать на приём. Telnet прицепил было, но через него node.restart из командной строки не передать. То есть не достигается финальная цель - нажал одну кнопку, и всё сделалось само :)

    В аттаче проект FTP с новыми командами.

    ← Предыдущее сообщение | Продолжение →
     

    Вложения:

    • FTP.ZIP
      Размер файла:
      10,5 КБ
      Просмотров:
      195
    Последнее редактирование модератором: 12 окт 2020
    swc и ИгорьК нравится это.
  16. serg3295

    serg3295 Гик

    ← Предыдущее сообщение

    Автоматизация возвращается


    В целях завершения реализации различных способов общения с ESP непосредственно из VSCode я добавил возможность закачки и запуска файлов по HTTP.
    Для исполнения команд требуется http сервер, разработанный ИгорьК. Сервер взят из поста «Грузим Lua скрипты по wifi» данной темы. В качестве инструмента со стороны PC так же, как и ранее, используется curl.

    При работе по http в режиме multipart/form-data curl разбивает стартовое сообщение POST на несколько кусочков. Это отличие от заголовка загрузки через оболочку сервера не позволяет реализовать загрузку файлов без корректировки кода http.lua, представленного ИгорьК. Пришлось внести небольшие изменения в код (они отмечены комментариями – for curl). Надеюсь, ничего не поломал :). Поправленный файл http.lua в аттаче.

    Для тех, у кого уже во всех устройствах зашит код от ИгорьК и менять ничего не хочется, можно предложить использовать вместо curl утилиту HHTPie, которая генерирует «правильный» стартовый заголовок (Требует Питона вер.>= 3.6). Тогда загрузка файла будет осуществляться командой типа:
    http -f POST http://192.168.1.69 filename=tt.lua myfile@tt.lua

    Однако, в приведённых файлах команд у меня используется только curl, соответственно, файл http.lua скорректированный.
    Свой IP адрес ESP’шки надо вбивать в файл http.txt, находящийся в каталоге .vscode.

    Итак, добавлены команды:
    • HTTP: Выгрузить текущий файл
    • HTTP: Запустить текущий файл
    • HTTP: Сброс ESP
    • LuaSrcDiet
    LuaSrcDiet – это утилита, которая экстремально сжимает файл *.lua перед выгрузкой на ESP. Устанавливается через luarocks из каталога c:\Program Files (x86)\Lua\5.1\ командой

    luarocks install luasrcdiet

    После выполнения команды LuaSrcDiet файл с ТЕМ ЖЕ именем кладётся в каталог .output. Оттуда его можно выгрузить на ESP. Эту команду можно далее встраивать в цепочку автоматизации, комбинируя её с уже имеющимися командами, по желанию.

    Дополнительно немного изменил структуру файлов скриптов, которые выкладывал здесь ранее. Теперь всё объединено в один скрипт auto.ps1. Скорректирован файл команд task.json. Размер LFS меняем в переменной lfsSize скрипта auto.ps1. Новые файлы команд и скрипта в файле vscode.zip в аттаче.

    UPD. Enhancement.
    Для того, чтобы запускать на исполнение файл по HTTP из любого каталога, а не только из верхнего надо заменить в файле task.json строчку команды. То есть, должно быть так:
    Код (C++):
    "label": "HTTP: Запустить текущий файл",
    "type": "shell",
    "command": "curl.exe --get -d command=runfile -d filename=${fileBasename} --config ./.vscode/http.txt",
    Для того, чтобы скомпилировать файл, находящийся в подкаталоге проекта нужно использовать следующую строчку команды
    Код (C++):
    "label": "Кросс компилятор",
    "type": "shell",
    "command": "luac.cross.exe -o ${workspaceFolder}/.output/${fileBasenameNoExtension}.lc  -l ${fileDirname}/${fileBasename}  > ${workspaceFolder}/.output/${fileBasenameNoExtension}.log",
    Важное дополнение ->
    ← Предыдущее сообщение
     

    Вложения:

    • vscode.zip
      Размер файла:
      2,8 КБ
      Просмотров:
      189
    • http.zip
      Размер файла:
      2,4 КБ
      Просмотров:
      191
    Последнее редактирование: 13 окт 2020
    swc и ИгорьК нравится это.
  17. ИгорьК

    ИгорьК Гуру

    Класс! Рекомендую поправить все посты, вставив в каждый ссылку на следующий в конце поста и вначале - на предыдущий. @NikitOS , помогите, пожалуйста!
    Великолепная работа.
     
    swc, NikitOS и serg3295 нравится это.
  18. ИгорьК

    ИгорьК Гуру

    Начнем с азов:

    upload_2020-10-12_12-20-27.png

    @serg3295 есть комментарии? Win10 домашняя. Запуск VS от имени администратора в т.ч.
     
    swc нравится это.
  19. serg3295

    serg3295 Гик

    Попробуйте в Powershell с правами админа набрать

    Set-ExecutionPolicy Unrestricted
    и согласиться большой буквой А

    Кажется, я отсюда брал.

    UPD. Извиняюсь, забыл про это написать. Очень давно устанавливал VSCode, и не учёл, что без этого скрипты не работают. Надо бы во второй мой пост про автоматизацию это добавить, так как это важно. Но возможность редактирования исчезает через сутки :(
     
    Последнее редактирование: 12 окт 2020
    swc и ИгорьК нравится это.
  20. ИгорьК

    ИгорьК Гуру

    От как забавно то :) cmd - и все работает, PowerShell - суперзащита :) Никогда не сталкивался и мыслей на оболочку не возникло. Грешил на NodeMCUTool
     
    swc нравится это.