首页 文章

使用Wifi将Lua脚本上传到NodeMCU

提问于
浏览
3

是否可以使用Wifi接口而不是串行将Lua脚本上传到NodeMCU?

我发现的教程和示例都使用串行接口,即电缆,来编程NodeMCU,但我想更改程序而不连接任何东西(使用智能手机或浏览器)

5 回答

  • 2

    对的,这是可能的 . 它是一种自制的选择,但它在一定程度上起作用 . 当然,唯一的限制是尺寸,但除此之外它的效果非常好 . 看一眼:

    http://www.instructables.com/id/ESP8266-WiFi-File-Management/

    你需要有一种方法来编写PHP程序(我用C#编写),如果你不能用你能下载的另一种语言编写代码并重用这个用户编写的内容并使用你自己的PHP服务器而你应该很好走 .

    如果您有任何疑问,请询问 .

  • 0

    我通过wifi上传所有模块 . 我首先以通常的方式(通过USB)上传一个 bootstrap.lua 程序 . 然后,该程序可用于上载实际(较大)有效载荷 . 这是引导程序:

    ip, mask, host = wifi.sta.getip()
    port, path, pgm = 80, "/upload", "u.lc"
    file.remove(pgm) ; file.open(pgm, "w+") payloadFound = false
    local conn = net.createConnection(net.TCP, 0)
    conn:on("connection", function(conn)
            conn:send("GET "..path.."/"..pgm.." HTTP/1.0\r\n".."Host: "..host.."\r\nConnection: close\r\nAccept: */*\r\n\r\n") end)
    conn:on("receive", function(conn, payload)
            if (payloadFound) then file.write(payload) file.flush()
            else payloadOffset = string.find(payload, "\r\n\r\n")
                    if (payloadOffset) then
                            file.write(string.sub(payload, payloadOffset + 4)) file.flush() payloadFound = true
                    end end end)
    conn:on("disconnection", function(conn) file.close() dofile(pgm) end) conn:connect(port,host)
    

    第一行使用网关服务器作为上载程序的Web服务器 . 第二行设置要上载的程序的端口( 80 ),路径( /upload )和名称( u.lc ) . 然后它获取文件并最终运行它(最后一行) .

    您必须在运行此无线连接之前激活无线连接,并且您的Web服务器当然应该处于活动状态,并且您的有效负载位于 /upload/u.lc 中 .

    当然,您可以更改硬连线值,甚至可以使它们动态化 .

    Headers ##这应该是您想要的简单起点 .

    顺便说一句,浓缩格式是为了使初始上传速度快,我使用 --dofile 选项上传 luatool.py .

    稍后更新程序( u.lc )是 dofile("bootstrap.lua") 的简单重复 .

    我的 u.lc 是一个阶段2引导程序,它上传了一长串文件(主要是 .lc ) . 对于这个简短的回答可能也太过牵扯 .

    最后,我应该提一下,这是基于https://github.com/Manawyrm/ESP8266-HTTP/

    HTH

  • 2

    我有另一个解决方案,没有大小限制 . 此外,它不需要任何其他Web服务器,您可以直接从工作站发送文件 . 下面的文件提供了上传和下载到芯片的内容 .

    不幸的是,它不使用Web浏览器使用的标准上载方案,最后提供了一个上传到它的javascript文件 . 可以在SendTo文件夹中创建js的快捷方式,从而将其添加到每个文件的上下文菜单中的“发送到”选项列表中,但它只能处理单个文件选择 . (处理选择的多个文件需要shell扩展 . )

    它确实支持常规浏览器下载 .

    请注意,此方案主要依赖于某种XMLHTTPRequest约定,即POST的主体在请求之后的第二帧/后续帧中发送 . 如果不是这种情况,则代码需要在初始请求的有效负载中找到第一个\ r \ n \ r \ n,并将随后的数据附加到文件中 .

    不用说,芯片必须在呼叫之前设置为AP .

    headerBlock = "\r\nContent-type: text/html\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\nCache-Control: no-cache\r\n\r\n"
    local currentFileName = ""
    local isPostData = false
    print("filexfer")
    local srv=net.createServer(net.TCP, 60) 
    srv:listen(80,
        function(conn) 
            local function writefile(name, mode, data)
                if (file.open("temp_" .. name, mode) == nil) then
                    return -1
                end
                file.write(data)
                file.close()
            end
            conn:on("disconnection", 
                function(conn) 
                    isPostData = false
                end
            )
            conn:on("sent", 
                function(conn) 
                    currentFileName = ""
                    isPostData = false
                    conn:close()
                end
            )
            conn:on("receive",
                function(conn, payload)
                    tmr.wdclr();
                    local s, e, m, buf, k, v
                    local tbl = {}
                    local i = 1
                    local retval = ""
    
                    if isPostData then
                        writefile(currentFileName, "a+", payload)
                    else
                        s, e = string.find(payload, "HTTP", 1, true)
                        if e ~= nil then
                            buf = string.sub(payload, 1, s - 2)
                            for m in string.gmatch(buf, "/?([%w+%p+][^/+]*)") do
                                tbl[i] = m
                                i = i + 1
                            end
                            m = nil
                            if #tbl > 2 then
                                local cmd = tbl[2]
                                if (tbl[3] ~= nil) and (tbl[3] ~= "/") then
                                    currentFileName = tbl[3]
                                --else return an error
                                end
    
                                if (cmd == "put") then
                                    writefile(currentFileName, "w+", "")
                                end
    
                                if (cmd == "append") then
                                    isPostData = true
                                end
    
                                if (cmd == "persist") then
                                    file.rename("temp_" .. currentFileName, currentFileName)
                                end
    
                                buf = ""
                                if retval == nil then
                                    retval = "[nil]"
                                end
                                buf = "HTTP/1.1 200 OK" .. headerBlock .. retval
                            else
                                local filename = "index.html"
                                if tbl[2] ~= nil and tbl[2] ~= "/" then
                                    filename = tbl[2]
                                end
                                require("fileupload")(conn, filename)
                                buf = ""
                            end
                            conn:send(buf)
                        end
                    end
                end
            ) 
        end
    )
    

    这是fileupload.lua,由要求接近第75行的调用引用(上载因为芯片正在将文件发送到请求主机 . )它使用常规浏览器便于下载任何大小的文件 . 如果没有传递文件名,则默认为“index.html” .

    local module =...
        return function(conn, fname)
            local buf
            tmr.wdclr()
            if file.list()[fname] ~= nil then
                file.open(fname, "r")
                buf = "HTTP/1.1 200 OK" .. headerBlock
            else
                file.open("error404.html", "r")
                buf = "HTTP/1.1 404 FILE NOT FOUND" .. headerBlock
            end
    
            conn:on ("sent",
                function(sck)
                    function sendfile(sck)
                        buf = file.read(255)
                        if buf ~= nil then 
                            sck:send(buf)
                        else
                            sck:close()
                            if module ~= nil then
                                package.loaded[module] = nil
                            end
                            module = nil
                            return
                        end
                    end
                    sck:on("sent", sendfile)
                    sck:on("disconnection",
                        function(sck)
                            print("[disconnection fileupload.sendfile]", node.heap())
                        end
                    )
                    sendfile(sck)
                end
            )
            conn:on ("receive",
                function(sck, pl)
                    sck:close()
                end
            )
            if buf == nil then
                buf = ""    
            end
            conn:send(buf)
        end
    

    这是用于上传到芯片的客户端javascript文件 . 将要上载的文件的完整路径或相对路径作为其第一个/唯一参数传递 . (如果没有传递args,则会抛出错误 . )

    var filepath = WScript.Arguments(0);
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var str = fso.OpenTextFile(filepath, 1);
    var file = fso.GetFile(filepath);
    var filename = file.Name;
    var buf = "";
    
    var xhr = new ActiveXObject("MSXML2.XMLHTTP.6.0");
    xhr.open("GET", "http://192.168.4.1/put/" + filename, false);
    xhr.send();
    
    while (str.AtEndOfStream == false)
    {
        buf = str.read(255);
        xhr.open("POST", "http://192.168.4.1/append/" + filename, false);
        xhr.send(buf);
    } 
    
    str.close();
    xhr.open("GET", "http://192.168.4.1/persist/" + filename, false);
    xhr.send();
    
  • 2

    上面描述了一种解决方案(http://www.instructables.com/id/ESP8266-WiFi-File-Management/),但使用桌面.NET应用程序代替PHP Web服务器https://github.com/Orudnev/.Net-WiFi-File-Manager-for-ESP8266 . 如果您不喜欢安装Web服务器可能会更方便,它足以启动FileManager.exe应用程序 .

  • 5

    如果您使用Esplorer作为IDE,则另一种方法是here

    它使用ESP8266上的telnet服务器,并将Esplorer串口重定向到telnet服务器的地址;这是一个Windows示例,但我已经设法使用Linux下的“socat”工作 .

    我发现的唯一问题是如果你想要多个tcp服务器,Nodemcu不允许,在这种情况下,可能另一个ESP8266充当tcp /串行控制台中继可能是答案 .

相关问题