9、nodeMCU学习笔记--net模块

esp8266  nodemcu  lua  wifi  net  web

闲言碎语

nodemcu的wifi模块,花了三篇文章被我水完了。内容还是比较浅显的。不过,nodemcu的开发者确实把wifi模块设计的很简单,也和容易使用。配置函数、station类函数、ap类函数、监听注册函数,总体来讲还是很清晰明了。要用熟这些wifi功能,其实还要配合其他模块一起来(比如这篇文章要说的net),循序渐进。

这里有个综合文章这里

模块函数

net模块的函数也是比较多的。不过,整体结构也是很清晰的。赶紧来看看这些函数

序号 函数名 参数 返回值
1 net.createConnection() type, secure net.socket 子模块
2 net.createServer() type, timeout net.server 子模块
3 net.multicastJoin() if_ip, multicast_ip
4 net.multicastLeave() if_ip, multicast_ip
5 net.server:close()
6 net.server:listen() port,[ip],function(net.socket)
7 net.server:on()
8 net.server:send()
9 net.socket:close() nil
10 net.socket:connect() port, ip / domain nil
11 net.socket:dns() domain, function(net.socket, ip)
12 net.socket:getpeer() ip, port
13 net.socket:hold()
14 net.socket:on() event, function() nil
15 net.socket:send() string[, function(sent)]
16 net.socket:unhold()
17 net.dns.getdnsserver() dns_index(0 / 1) ip
18 net.dns.resolve() host, function(ip) nil
19 net.dns.setdnsserver() dns_ip_addr, dns_index nil
20 net.cert.verify() enable / pemdata true

参数里面有个type的,只有两种选择,要么net.TCP,要么net.UDP。有几个server相关的API,几个socket相关的API。这里不打算一个一个函数的讲了,直接来几个例子反而更容易理解API的含义。

实践一下

光说不练假把式,直接来实践一下。从API中可以知道,net模块可以创建server和client。实践前,确保nodemcu已经连入网络。

  • 先使用wifi.setmode()配置为STATION模式或者STATIONAP模式;
  • 接着用wifi.sta.config()配置ssid和密码;
  • 可能还需要使用wifi.sta.connect()来让设备连入网络。

wifi的配置后会一直生效。如果你先前配置过,可以不用配置。当然,重新配置一下也可以。

client

这里先来看看如何创建一个client,以及如何进行通信。

cl = net.createConnection(net.TCP, 0)
cl:connect(9999, "192.168.199.101")
cl:on("receive", function(sck, c) print(c) end)
cl:on("disconnection", function(sck, c) print("disconnection!") end)

使用.createConnection创建一个net.TCP客户端,函数会返回一个socket子模块,后面要用的都是socket相关的函数,第二个参数,1表示加密,0表示不加密。net.socket:connect用来连接到服务端。参数2既可以是ip地址,也可以是域名。注意connect前面用的是冒号:,不是点。接着,找一个网络调试工具来创建一个server。这里我找了个名字叫网络调试的手机APP。net.socket:on函数用来绑定几个事件回调,函数原型是这样的 function(net.socket[, string]):

  • "connection" : 连接;
  • "reconnection" : 重连接;
  • "disconnection" : 断开连接;
  • "receive" : 接收回调,string表示接收到的字符串数据;
  • "sent" : 发送;

这个例子里面,nodemcu连接到app创建的server后,并没有产生回调事件,具体是什么原因,不清楚。不过,尝试连接到域名却可以产生回调事件。比如下面这个域名

cl:connect(80, "www.nodemcu.com")
9、nodeMCU学习笔记--net模块_第1张图片
客户端

9、nodeMCU学习笔记--net模块_第2张图片
服务端

点击APP左边的客户端列表,断开nodemcu,得到一个预期的断开回调。使用 .createConnection创建多个客户端。比如,这样子:

cl = net.createConnection(net.TCP, 0)
cl2 = net.createConnection(net.TCP, 0)

使用net.socket:send可以向服务端发送数据。比方说在ESPlorer右边的输入框里面输入下面这句语句:

=cl:send("Hello NodeMCU")

这里需要说明的是,send函数发送的数据长度是有限度的,大概是1400多个字节。当要发送大于1400字节的内容的时候,比如说发送一个带css、js的网页,就需要分成多次发送。多次发送也不是简单的把上面的代码复制几遍就能解决的。而是要用到"sent"事件来回调。

cnt = 0
cl = net.createConnection(net.TCP, 0)
cl:connect(9999, "192.168.199.101")
cl:on("receive", function(sck, c) print(c) end)
cl:on("disconnection", function(sck, c) print("disconnection!") end)
cl:on("sent", function(c) 
    if cnt ~= 10 then
        cl:send(cnt)
        cnt = cnt + 1
    end 
end)

这个例子可以让客户端在发送完第一条消息后,再发10条消息给服务端。激活的方法还是在ESPlorer中输入一条send语句。

=cl:send("Hello NodeMCU")

当nodemcu发送完第一条语句后,会触发"sent"事件,进而发送10条消息给服务端。

9、nodeMCU学习笔记--net模块_第3张图片
收到消息了!

server

知道了如何创建并使用一个client后,我们来继续看如何创建一个server。先上个开胃菜。

ns = net.createServer(net.TCP, 15)
ns:listen(80, function(c)
    c:on("receive", function(c, d)
        print(d)
        c:send(d)
    end)
    c:on("connection", function(c, d) print(d) end)
    c:on("disconnection", function(c, d) print("disconnection") end)
end)

使用.createServer创建一个net.TCP的服务端,第二次参数用于设置不活动连接的超时时间,返回一个net.server模块。nodemcu只能创建一个server,不像client可以创建多个。需要注意一下。net.server只有4个函数,其中的send和on仅对udp有用。tcp要使用socket的send和on函数。
  接着用net.server:listen创建一个监听。回调传入的是一个socket。可以尽情的使用socket的函数了,比如用net.socket:on设置各种事件回调。这个例子里面的"connection"依然没效果╮(╯_╰)╭。使用APP连接到创建好的server,试着发送信息。

9、nodeMCU学习笔记--net模块_第4张图片
这图有点大啊 ╮(╯_╰)╭

  接着到主菜上场了。内容有点长。主要是实现上篇文章说的 enduser setup。动筷子前记得把wifi模式设置成AP模式或者混合模式。

web = 'Connect gadget to you WiFi

WiFi Login

Connect gadget to your WiFi

' sendBuf = {} for i = 1, #web, 1400 do local len = #web - i if len > 1400 then sendBuf[#sendBuf + 1] = string.sub(web, i, i+1400-1) else sendBuf[#sendBuf + 1] = string.sub(web, i, i+len) end end

web数组存储了一个web页面。当然了,这个web页面比较大,远远超过了1400字节。需要将它分成几块,以便后面分批发送。所以,把这个web页面分块存储到一个table中。

function sendWeb(c)
    if #sendBuf > 0 then
        s = table.remove(sendBuf, 1)
        c:send(s)
    else
        c:close()
    end
end

函数sendWeb用来把table里面的内容发送出去,一边发送,一边remove表里面的内容,所以用浏览器浏览只能打开页面一次 o(╯□╰)o。或许这个地方可以优化一下。

sv = net.createServer(net.TCP, 60)

sv:listen(80, function(c)
    c:on("receive", function(cn, req)
        local _, _, method, path, vars = string.find(req, "([A-Z]+) (.+)?(.+) HTTP")
        if method == nil then
            _, _, method, path = string.find(req, "([A-Z]+) (.+) HTTP")
        end

        local _GET = {}
        if vars ~= nil then
            for k, v in string.gmatch(vars, "(%w+_%w+)=(%w+)&*") do
                _GET[k] = v
                print(k .. ":" .. v)
            end        
            local sendbuf = "

Config Succeed!

" sendbuf = sendbuf.."

wifi_ssid: ".._GET["wifi_ssid"].."

" sendbuf = sendbuf.."

wifi_password :".._GET["wifi_password"].."

" cn:send(sendbuf) cn:close() else cn:on("sent", sendWeb) sendWeb(cn) end end) end)

最后这一部分,和开胃菜那个例子的效果差不多,只是这回发送的是一个页面。回调函数中,先解析浏览器get过来的内容,之后把类似于这种格式的字符串("wifi_ssid=hello&wifi_password=12345678")存储到一个table中。最后又把提取到的内容send出来,赶紧用浏览器访问nodemcu看看效果吧。只需要在浏览器的地址栏输入ip地址即可。
  利用net的server,还可以显示web控制led之类的效果,网上有相关的例子。或者可以配合nodemcu上面的AD完成更多东西来。不过前提是,要能写出漂亮的web页面o(╯□╰)o。

一点lua语法

local _, _, method, path, vars = string.find(req, "([A-Z]+) (.+)?(.+) HTTP")

这个地方的 _ 实际上是一个变量,叫虚变量,因为string的find方法会返回子串的起始和结束地址。不需要的话,可以用虚变量来存储。

评论不能贴图, 如有需要可以到我的GitHub上提issues

你可能感兴趣的:(9、nodeMCU学习笔记--net模块)