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

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

  1. serg3295

    serg3295 Гуру

    Можно написать функцию так
    Код (C++):
    ---@param x boolean
    ---@return integer
    local function toNum(x)
      return x and 1 or 0
    end

    print(toNum(false))
    Только непонятно, у вас параметр функции всё-таки boolean, или boolean | number?

    Есть ещё функция tonumber() - пытается преобразовать переданный параметр в число, иначе возвращает nil
     
    ИгорьК нравится это.
  2. Sergku

    Sergku Нерд

    с отсутствием данных все понятно, интересовало именно 0, 1 (пины же определенное значение возвращают).
     
    ИгорьК нравится это.
  3. Sergku

    Sergku Нерд

    благодарю, почитаю сейчас
     
  4. ИгорьК

    ИгорьК Гуру

    Смотрите в чем дело.
    Предположим, у вас пропало соединение с wifi и вы его проверяете.
    Три варианта.
    Привычные:
    wifi = false
    wifi = 0
    Lua:
    wifi = nil

    В чем прелесть последнего? Освободили память.

    В общем, логика 0 == true заключается в том, что в lua достаточно средств проверки действительности событий без участия нуля. А если 0 - число, то это есть данные.
     
  5. ИгорьК

    ИгорьК Гуру

    0 и 1 в данном случае - значения, а не отсутствие чего-то, не так ли?
     
  6. ИгорьК

    ИгорьК Гуру

    ИМХО, плохая практика.
     
  7. ИгорьК

    ИгорьК Гуру

    Проверьте данные на 1 вместо всего вашего кода для данной ситуации.

    Заметьте, что в случае Си при отсутствии данных у вас вылетит ошибка. И где по-настоящему изврат? ;)
     
  8. Sergku

    Sergku Нерд

    Дык я затем и спросил, что мне моя реализация не очень нравится :)
     
  9. ИгорьК

    ИгорьК Гуру

    Код (Lua):
    if Val == 1 then...
    И это работает для всех случаев.

    Правда работает плохо, если вы хотите убедиться, что и 0 там бывает. То есть, повторюсь, не путаете данные 0 с их отсутствием в целом.
     
  10. 8bitai

    8bitai Нерд

    Код (C++):
    local input = "foo = b_ar, bar=fo#o"

    for key, value in input:gmatch("(%w+)%s*=%s*(%w+)") do
        print("key: " .. key .. ", value: " .. value)
    end
     
    Не могу понять в чем дело вроде работал раньше такой код и захватывал все символы так что результат был таким
    key: foo, value: b_ar
    key: bar, value: fo#o
    а сейчас не захватывает и результат такой
    key: foo, value: b
    key: bar, value: fo
    прошивку вроде не менял
    NodeMCU 3.0.0 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
    задал вопрос ИИ он отвечает что всё должно работать как я предполагаю
    Код (C++):
    Detailed Answer: Capturing All Symbols as Key Values in Lua
    Question Summary
    The user wants to know how to capture all symbols as key values in Lua using the given code snippet.

    Answer
    To capture all symbols as key values in Lua, you can modify the provided code snippet as follows:

    language-lua
    Copy code
    local input = "foo = b_ar, bar=fo#o"

    for key, value in input:gmatch("(%w+)%s*=%s*(%w+)") do
        print("key: " .. key .. ", value: " .. value)
    end
    In the modified code, we assign the input string to a variable named input. Then, we use the gmatch function to iterate over the matches in the input string.

    The pattern (%w+)%s*=%s*(%w+) is used to capture the key-value pairs. Here's a breakdown of the pattern:

    (%w+): Matches one or more alphanumeric characters (letters, digits, and underscores) and captures them as the key.
    %s*=%s*: Matches zero or more whitespace characters followed by an equal sign (=) and zero or more whitespace characters.
    (%w+): Matches one or more alphanumeric characters and captures them as the value.
    Inside the loop, we print the key and value for each match. The output will be:

    key: foo, value: b_ar
    key: bar, value: fo#o
    By using this modified code, you can capture all symbols as key values in Lua.
     
    Последнее редактирование: 5 окт 2023
  11. serg3295

    serg3295 Гуру

    Не имею что сказать за искуственный интеллект, но есть сомнения, что этот код работал как ожидалось.
    Поскольку в Lua %w, alphanumeric characters (A-Z, a-z, 0-9)
    Попробуйте вот такой шаблон. Это должно помочь.
    (%w+)%s*=%s*([#_%w]+)
     
    8bitai и ИгорьК нравится это.
  12. obuhanoe

    obuhanoe Гик

    Добрый день.
    Решил закинуть красивые картинки в свой сервер, в base64 - одна картинка весит более 3000 байт, при отправке sck:send(line) ругается out of memory, что логично большие данные не переваривает.
    Решил сделать в цикле, и отправлять по 100-1000 байт и все равно падает с ошибкой out of memory , после отправке 2500 байт примерно.
    Пока не могу понять в чем причина. Есть идеи в чем может быть проблема?
    Код (Lua):
    if file.open("page.lua", "r") then
       repeat
            local line = file.readline()
            local j = 0
            if line then
                if dat.graph ~= nil then
                   line = string.gsub(line, "$(%w+)", dat)
                end
                -- отправка по 1000 байт
                if #line > 1000 then
                    print(#line)
                    for i = 0, math.ceil(#line/1000)-1 do
                        sck:send(line:sub(j,j+1000))
                        j = (j + 1000) + 1
                    end
                else
                    sck:send(line)
                end
            end
        until line == nil
        file.close()
    else
      sck:close()
    end
     
  13. ИгорьК

    ИгорьК Гуру

    @obuhanoe, я же неоднократно писал и документация объясняет что циклы свыше 15 мс нежелательны, а цикл на 500 мс вызывает злую собаку.

    Надо переписывать таким образом, чтобы отправка осуществлялась кусочками функцией, которая, в свою очередь, вызывается из цикла. Этот вызов не прямой, а, еще лучше, с применением функции node.task.post(). Но это надо проверять.

    П.С. посмотрел ещё раз, чёт не понимаю ваш код со смартфона, а компа для более пристального анализа нет. Полагаю, ваша картинка считывается в line за один раз? Не проще ли разбить её в файле на части и отправлять кусочками?
     
    Последнее редактирование: 23 янв 2024
  14. ИгорьК

    ИгорьК Гуру

    В добавление.

    Код (Lua):
    for i = 0, math.ceil(#line/1000)-1 do
        sck:send(line:sub(j,j+1000))
        j = (j + 1000) + 1
    end
    Цикл for ... end - это такая сволочь, что рубит невзирая ни на что. Он вызывает асинхронную функцию sck:send(line:sub(j,j+1000)) - которая работает некоторое время. Цикл практически одномоментно копирует line кусочками (увеличивая массив данных) и всю массу ставит в очередь на отправку. Ясный пень, немногая память забивается.

    То есть, а данном случае выходом будет чтение фотографии не всем файлом, а разбиение его на части уже в заготовке, в файле. Второй вариант - понять что там с callback sck:send() и работать через него. То есть эта функция отработала и callback вызывает передачу новой порции данных. Но первый способ проще и лучше. Там будет наименьшая и регулируемая загрузка памяти.
     
    obuhanoe нравится это.
  15. obuhanoe

    obuhanoe Гик

    Общее направление понял, как что получится отпишусь.
    Спасибо
     
    ИгорьК нравится это.
  16. obuhanoe

    obuhanoe Гик

    Игорь возможно я не так Вас понял сделал вот как:
    в server.lua
    Код (Lua):
    local dat = {
                         datatime = nil,
                         ram      = nil,
                         graph    = nil
                         ,lamp1   = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB2AAAAdgB+lymcgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAnJSURBVHic7Zt7dFTFHcc/s3d3s9kNm83mCSYEkUQTQBMQEEWNBVqBIgVRUOQQ0VpArVp8FLRVpK1aCvgqaj34aIOmoC0HgwhUHiGRI8SgGBQUkACmIGIChAQ22Z3+cXfzMI993HvDqe33nD3n7szc33x/v7n3N7+Z31wID9kCvgNkF//qk1326V8tzndNGtw7UwhxpIN2x4GccBQyh2mAHAlx3WxmnDZLqwohQDEpYYoLDVazyfbEpMFLrYpn6bzrB7L7SA01pz2t2lTXeThZ73ED2cDHocoO1wAA3DAwjVl5F7QWpCgkJsRHIi4sdIu28O7917Ypf6roE55dtytseREZ4OSZBr6uqW9VppgU6kRtJOJ0QU2dJ3gjHTCZrn//w/1NDkehcJ+ADcDbQGwH9RcBqW53ElFR0a0qFMWMxWINs7tm1NXVcvToIYDDwO4Omp3wcwwZImJG7ePPwKzhwyeQmtq7VYXD4cTtTopY8N69FRQWPg+wBLhTC8mWiMgHBEN19TcoSusZwWazc+LE8Yhl+kdfd+htgEaA8vISncW27UMv6G2AFwEXEP298muAhD59+rfyAzabDSFMrRp6PGepqNgG8C2w8Xty6v196Aa9DfA5MK2d8mLgytGjb8bpjGsqTErqjtnSOqCqrj7Gw3O3BWTdqDO/NjAFb/LDxv+8AQyZBVpAQX3/'
                         ,lamp2   = 'uwNUVGzDZrM3VTqdLvr1H9Q0PR74ag9ffLkzUN0dGIHqB7wG8zQE0UApQSK3nJxB36xc9cHGlas+2OhwdDvbTpsSwGYUSb0DoZaYDfwpNzeXkSNHNhVaLArWKNXxmUwmRo8eRUZGHwA2b95CeXl5U9uid95l+/aygKxFRpA00gCvAvkFBQUMHTq0qdAZ6yAqytLxXS2waVMx140dH5A13QiSRvqAciB//vz55OXlNXdoVrBaQzPA2rXrApcf6U2uK2ABVqN9dVfkl/VfCQEMBD4D5JJHhsi/L7hKJsbZpBDI5UvGyeVLxkkhkInxdrl8yTj5wu9/HFD8M/+9Rr6mXYZiQFaunSB9n0yV6T1ipBBIWfmQlJUPSSGQ6ec5pax8SB7cOjNggOKuINZVgVAko9glI99VBkgQAuJdUcEbuu0IVXW30aSgawzQXQgy0lIc2G3BJ51om5m07k6ADCDFaHJdYYA5UqLcNKpXc4novNsp47NB9fyPGMgLMN4AvwLuSoyzcc+ULLXE6gh60723DSIpwS6BWcD9RhI0ygBO4E1goSPaLJY9OYyUhGiIikFEd7Sf2oykeDtvPnedcNgtAAuAQjreiNUEIwzQUwjKgMm9esRQ/NpPGDG0B8LhRkQ7Q/btP7o8nZK3bxHnp8UCTAK2Aml6k9XbAOlCUCwlGdflpVK+fAy5WQmIbglgCX9Bl5OdxI41tzJ2RB+ALNSV4Xl6EtbTAA5gpZSk3zKmN28tysPltCFi4sEUeSQb2y2Kf7w0nik/'
                         ,lamp3   = 'ywboiRoa2zu/K3ToaYBngJzhQ1J4Zf7lmBWBsLtA0R7Gm80mXl04hhHDeoGa/V2gWagfehlgGDA9Od5G4R+vwqwIsNojeuw7gsVsYtmzY0mMt0tgJnCZHnL1MsATgFgwe6Aa7QmhOjydkRRvZ8HcawSqK31KD5l6GOAyYFh271imjPanw6z2oMFOpJg6oS/ZGQkAVwEDtMrTg+VUgF9OyQrE8IiojoOd6hNn8Mnm6+oTZwDwSZquO4PJJLhrWpPet0bM2g89VlyHFJNIrdowkcQ4GygWRLfEVg2khMefKeWZV8qCKhkXa+O+2wfxyN2XNxn0+zh2vI7ulz6P1ycrgV5ayGt9AtKA1Nwst6o8gLltCvzVFTt5bHEJngYvA/olY7WoidOB/VMY2F9d71gtCgP6JeNp8PLbhVt4/a1PO+w0Md5OTt9kgHQgVYsCWg3QH+CSzOZ0lzC1XfGtWr8XgHUFk/hodT4piQ5MJkFZ0TTKiqZhMglSEh18tDqf9/6qZsNWrvuy044H9EsOXGZqUUDrpmgKQM8eLd75dg5KuZzqPsD6LQeoOlpL1Te1XJDuaqo/Py2Wyq9P8vaaPXy6+xgAblfnU+jsOwaz/2DNhvdLK7drUUDrExADEBPdIthpx/vfd/sgbFFmHltcwg0zV9LY6GPOrOat8jl3DqWx0cfEGSuZ93Qptigz904f1GnHF/'
                         ,lamp4   = 'Z28683Jm8GTmlRQOsT4AOoO9MyZS/bNLokK4myomm8WLCD0/UN3DjmIq7Naz5Bctuki+mRHMOK1btxRFuYOTU3MNV1im+r6zTS1z4L3Aws+8XETF74zRBVoN2lxgEGY9HL23ngDxsbfT45AOjYYwaB1lfgS4CDR043FUhf1+Qx12zaj88nzWgcRK0G2CUEnq2fHMPT4FNLGo0/r+f1Sj7cUYUQnAQqtMjSaoA6KSmtOeXh/Q//rZY0ngXp0yi2c5RsP8yp0x6kpBS/H4oUeoTChQCFaw40lzSc1UFsx3j+9aZU4d+0ytIjFHYKwUHFJGJ3rPgpfS9wgWJGxCTSYSyrAfsP1pCZ97L0+XxVUnI+0KBFnh5PwEkpWdTolTyw0D8y3kZoCL6wCRdSwoy5a/F6fUJKFqNReYjMAEnAS8AuoIe/bAGw/73SKl5Y/oVKtv4k6Dwj/OWNj1m/5QBAGeoOFH4Ou/ycwj6KGo4BrKgnNb4A7kBNXQUcUD0wRQjO3vPkNtZtrQLpRdZVq8OmA9Zs2s/dj66XQuAB8mk+MCn9XO7wc5vt5xoSwvnCYQ3qVpQCPAfcgHqYMYDDwF6f5PpVGw+L/plxZKY5QPoQ5ihN/mBd8VeM//k/ZUODV0rJTcDmFtW1wFLUc0RXAKOAIUBBKLLDMcAVwCFgIrAMaO8lrwBqPQ2+kYXvHRCKIrjyEjf4GhEWW9hG8Hol854uZcactTQ0+iTqyBe20/QMsBZYgbpA2+f/HxRGpaDHCSEKpJQxuRe5+d3dOYy6uhci2gXm0HaJ3924j0cXlVC28whCiO+klPnAO3oTNTIH3xd4DbgUYHC/'
                         ,lamp5   = 'BCaM7MnY4Rlk902FdvYNdu87zuoN+yhc9TllO48Eit9HHfnDRpA0+hCCCbgF+DVqZgeAJLeNzF4uXLE2JCYOHTlF1dFavv2u1Wc4JcDjwHqDORqC62mhMKqhrwAWAuUCPLQ9DFWHqvRc2n76lgXcZDBn3TAWVaE3O2ljRk1zXYyqXLAkQqFf5lg9CBoJK7AHlewoHeWO8MvcCwQ/Z3MO8SAq0VC99YPAwyG2LfLLfiACXl0CAVQDZ4ELQ7znOOqnuKHgQr/sanR03noflV2KGpfvCbF9OKH4HmAG6qexPxhU+3/nDP//YuQc91+K+l6fM/wHpEca3+mLWGUAAAAASUVORK5CYII=">'                

                        }

    if file.open("page.lua", "r") then
                   repeat
                        local line = file.readline()
                        if line then
                            if dat.graph ~= nil then
                               line = string.gsub(line, "$(%w+)", dat)
                            end
                            print(line)
                            sck:send(line)
                        end
                    until line == nil
                    file.close()
                else
                  sck:close()
                end
    Все равно происходит ошибка
    PANIC: unprotected error in call to Lua API (server.lua:85: out of memory) на строке sck:send(line)


    В page.lua
    <p>$lamp1$lamp2$lamp3$lamp4$lamp5</p>

    Если же Вы имели ввиду, что картинку нужно разбить на части и хранить в разных строках page.lua, то такой вариант не подходит потому что часть картинок будет подгружаться динамически - например включена лампа - отображается одна картинка, выключена - другая и так далее.
     
  17. ИгорьК

    ИгорьК Гуру

    Да именно это я и имел в виду. file.readline(), читает файл построчно, где "Lines are defined as zero or more bytes ending with a EOL ('\n') byte". Соответственно эти '\n' можно расставлять через какое угодно количество символов.

    Не совсем ясно, почему такой вариант не подходит - грузите себе что хотите и когда хотите. На каждую лампу сделайте свой файл, битый на части '\n' .

    То что вы делаете сейчас - заталкиваете в один файл все изображения, не есть правильно.

    ------------------------------------

    Никакие циклы ни for, repeat в данном случае не применимы. Отправка осуществляется через callback функции sck:send(...).

    Смотрите внимательно документацию здесь и здесь. В примерах данные вытаскиваются из таблицы, вам же их надо брать из чтения файла.
     
  18. ИгорьК

    ИгорьК Гуру

    Выглядеть в части отправки это должно ПРИБЛИЗИТЕЛЬНО (это не рабочий пример, а направление мысли) так:
    Код (Lua):
    isdata = true

    function getline()
        if file.open("pict.lua", "r") then
            local ln = file.readline()
            if ln then
                return ln
            else
                file.close()
                isdata = false
            end
        end
    end


    function receiver(sck, data)
      local function send(localSocket)
        if isdata then
          localSocket:send(getline())
        else
          localSocket:close()
        end
      end
    end
     
    obuhanoe нравится это.
  19. obuhanoe

    obuhanoe Гик

    Игорь, спасибо за помощь
    Написал вот так:
    Код (Lua):
            local is_data = true      
            local function pict_getline()
                if file.open("lamp.lua", "r") then            
                    repeat
                        local line = file.readline()
                        --print(line)
                        if line then                      
                            return line
                        end
                    until line == nil
                    file.close()
                    is_data = false
                end
            end
         
            local function send_pict(localSocket)
               if is_data then
                  localSocket:send(pict_getline())
               else
                  localSocket:close()
               end
            end
         
            local function send()
                if file.open("page.lua", "r") then
                   repeat
                        local line = file.readline()
                        if line then
                            if dat.graph ~= nil then
                               line = string.gsub(line, "$(%w+)", dat)
                            end                      
                            sck:send(line)
                            --send_pict(sck)   -- <<<<<<< 1
                        end
                    until line == nil
                    file.close()
                else
                  sck:close()
                end          
            end
    До конца не понимаю куда вставлять метод, который вытаскивает из файла картинку.
    Файл lamp.lua содержит одну строку в которую я добавил "\n" на каждые 1000 символов.
    Пример (часть):
    Код (Text):
    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB2AAAAdgB+lymcgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAnJSURBVHic7Zt7dFTFHcc/s3d3s9kNm83mCSYEkUQTQBMQEEWNBVqBIgVRUOQQ0VpArVp8FLRVpK1aCvgqaj34aIOmoC0HgwhUHiGRI8SgGBQUkACmIGIChAQ22Z3+cXfzMI993HvDqe33nD3n7szc33x/v7n3N7+Z31wID9kCvgNkF//qk1326V8tzndNGtw7UwhxpIN2x4GccBQyh2mAHAlx3WxmnDZLqwohQDEpYYoLDVazyfbEpMFLrYpn6bzrB7L7SA01pz2t2lTXeThZ73ED2cDHocoO1wAA3DAwjVl5F7QWpCgkJsRHIi4sdIu28O7917Ypf6roE55dtytseREZ4OSZBr6uqW9VppgU6kRtJOJ0QU2dJ3gjHTCZrn//w/1NDkehcJ+ADcDbQGwH9RcBqW53ElFR0a0qFMWMxWINs7tm1NXVcvToIYDDwO4Omp3wcwwZImJG7ePPwKzhwyeQmtq7VYXD4cTtTopY8N69FRQWPg+wBLhTC8mWiMgHBEN19TcoSusZwWazc+LE8Yhl+kdfd+htgEaA8vISncW27UMv6G2AFwEXEP298muAhD59+rfyAzabDSFMrRp6PGepqNgG8C2w8Xty6v196Aa9DfA5MK2d8mLgytGjb8bpjGsqTErqjtnSOqCqrj7Gw3O3BWTdqDO/NjAFb/LDxv+8AQyZBVpAQX3/uwNUVGzDZrM3VTqdLvr1H9Q0PR74ag9ffLkzUN0dGIHqB7wG8zQE0UApQSK3nJxB36xc9cHGlas+2OhwdDvbTpsSwGYUSb0DoZaYDfwpNzeXkSNHNh\nVaL........
    Если вставляю как указано <<<<<<< то получаю ошибку out of memory в строке localSocket:send(pict_getline())
    Чувствую что упускаю какую то деталь.
     
  20. ИгорьК

    ИгорьК Гуру

    До среды никак...
     
    obuhanoe нравится это.