nodeMCU Lua ESP8266第三課 內網控制LED

寫在前面的話:個人學習筆記,拋磚引玉,希望有興趣的人加入QQ羣415469069一起討論,歡迎有共同愛好的人。 

本教程以ESP-12N,CP2102開發板爲例進行講解。

  • 代碼。

--wifi_light.lua

wifi.setmode(wifi.STATION)  

wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")  

print(wifi.sta.getip())  

led1 = 0   

gpio.mode(led1, gpio.OUTPUT)  

srv=net.createServer(net.TCP)  

srv:listen(80,function(conn)  

    conn:on("receive", function(client,request)  

        local buf = "";  

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

        if(method == nil)then  

            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");  

        end  

        local _GET = {}  

        if (vars ~= nil)then  

            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do  

                _GET[k] = v  

            end  

        end  

        buf = buf.."<h1> ESP8266 Web Server</h1>";  

        buf = buf.."<p>GPIO16 <a href=\"?pin=ON1\"><button>ON</button></a> <a href=\"?pin=OFF1\"><button>OFF</button></a></p>";  

        if(_GET.pin == "ON1")then  

              gpio.write(led1, gpio.LOW);  

        elseif(_GET.pin == "OFF1")then  

              gpio.write(led1, gpio.HIGH);  

        end  

        client:send(buf);  

        client:close();  

        collectgarbage();  

    end)  

end)  

 

二、說明:

  1. ,wifi模式爲station,輸入wifi名和密碼進行配置。

句法:wifi.setmode(mode[, save])

作用:配置WiFi模式使用

參數:

mode 價值應該是其中之一

wifi.STATION:當設備連接到WiFi路由器時。這通常是爲了讓設備訪問互聯網。

wifi.SOFTAP: 因爲當設備只作爲一個接入點。這將允許您在WiFi網絡列表中查看設備(當然,除非您隱藏SSID)。在這種模式下,您的計算機可以連接到設備,創建一個局域網。除非您更改該值,否則NodeMCU設備將被分配一個本地IP地址192.168.4.1,併爲您的計算機分配下一個可用的IP地址,例如192.168.4.2。

wifi.STATIONAP:是的組合wifi.STATION和wifi.SOFTAP。它允許您創建本地WiFi連接並連接到另一個WiFi路由器。

wifi.NULLMODE:將WiFi模式更改爲NULL_MODE將使wifi進入與MODEM_SLEEP類似的低功耗狀態,但未提供wifi.nullmodesleep(false)。

save 選擇是否將wifi模式保存到閃存

true:WiFi模式配置將在電源週期中保留。(默認)

false:WiFi模式配置將不會通過重新啓動進行保留。

  1. led = 0,對應的是GPIO16,開發板上這個引腳外焊了個led,可以利用。
  2. 創建服務器,監聽80端口。

句法:net.createServer([type[, timeout]])

作用:創建一個服務器。

參數:

type:   net.TCP (默認)或 net.UDP

Timeout: 對於TCP服務器,超時時間爲1〜28'800秒,默認30秒(非活動客戶端斷開連接)

返回:

net.TCP 時返回: net.server子模塊

net.UDP時返回: net.udpsocket子模塊

句法:net.server:listen([port],[ip],function(net.socket))

作用:從IP地址偵聽端口。

參數:

port: 端口號,可以省略(隨機端口將被選中)

ip: IP地址字符串,可以省略

function(net.socket): 回調函數,如果連接成功創建,則傳遞給調用者函數

第一個參數:

回調的第一個參數是套接字(即socket)。

第二個參數:

如果事件是“接收”,則第二個參數是以字符串形式接收的數據。

如果事件是“斷開”或“重新連接”,則第二個參數是錯誤代碼。

如果指定了重新連接事件,則斷開只接收“正常關閉”事件。

否則,所有連接錯誤(正常關閉)傳遞到斷開連接事件。

句法:net.socket:on(event, function())

作用:註冊特定事件的回調函數

參數:

event: 字符串,可以是“連接”,“重新連接”,“斷開”,“接收”或“發送”

function(net.socket[, string]):回調函數。可以nil刪除回調。

句法:net.socket:send(string[, function(sent)])

參數:

string:        字符串中的數據將被髮送到服務器

function(sent): 用於發送字符串的回調函數

句法:net.socket:close()

作用:關閉嵌套字

  1. 處理接收的數據(即字符串request的內容)

關鍵字local:定義局部變量。

_,    指聲明虛變量,說白了就是我不想要前兩個返回值,給他個虛變量名,以後不會調用此數據。

string.find (str, substr, [init, [end]])
    在一個指定的目標字符串中搜索指定的內容(第三個參數爲索引),返回其具體位置。不存在則返回 nil。

第一個返回值:起始位置。

第二個返回值:終止位置。

string.gmatch(s, pattern)

會返回一個迭代器函數,通過這個函數可以遍歷到一個字符串中所有出現指定模式的地方。這個函數可以通過泛型for提取數據。

匹配模式

Lua 中的匹配模式直接用常規的字符串來描述。 它用於模式匹配函數 string.find, string.gmatch, string.gsub, string.match。

你還可以在模式串中使用字符類。

字符類指可以匹配一個特定字符集合內任何字符的模式項。比如,字符類%d匹配任意數字。所以你可以使用模式串 '%d%d/%d%d/%d%d%d%d' 搜索 dd/mm/yyyy 格式的日期:

s = "Deadline is 30/05/1999, firm"

date = "%d%d/%d%d/%d%d%d%d"print(string.sub(s, string.find(s, date)))    --> 30/05/1999

下面的表列出了Lua支持的所有字符類:

單個字符(除 ^$()%.[]*+-? 外): 與該字符自身配對。

當上述的字符類用大寫書寫時, 表示與非此字符類的任何字符配對. 例如, %S表示與任何非空白字符配對.例如,'%A'非字母的字符。

.

與任意字符配對

%a

與任意字母配對

%c

與任何控制符配對(例如\n)

%d

與任何數字配對

%l

與任何小寫字母配對

%p

與任何標點(punctuation)配對

%s

與空白字符配對

%u

與任何大寫字母配對

%w

與任何字母/數字配對

%x

與任何十六進制數配對

%z

與任何代表0的字符配對

%x(此處x是非字母非數字字符)

與字符x配對. 主要用來處理表達式中有功能的字符(^$()%.[]*+-?)的配對問題, 例如%%與%配對

[數個字符類]

與任何[]中包含的字符類配對. 例如[%w_]與任何字母/數字, 或下劃線符號(_)配對

[^數個字符類]

與任何不包含在[]中的字符類配對. 例如[^%s]與任何非空白字符配對

在模式匹配中有一些特殊字符,他們有特殊的意義,Lua中的特殊字符如下:

( ) . % + - * ? [ ^ $

'%' 用作特殊字符的轉義字符,因此 '%.' 匹配點;'%%' 匹配字符 '%'。轉義字符 '%'不僅可以用來轉義特殊字符,還可以用於所有的非字母的字符。

模式條目可以是

單個字符類

匹配該類別中任意單個字符

單個字符類跟一個 '*'

將匹配零或多個該類的字符。 這個條目總是匹配儘可能長的串

單個字符類跟一個 '+'

將匹配一或更多個該類的字符。 這個條目總是匹配儘可能長的串

單個字符類跟一個 '-'

將匹配零或更多個該類的字符。 和 '*' 不同, 這個條目總是匹配儘可能短的串

單個字符類跟一個 '?'

將匹配零或一個該類的字符。 只要有可能,它會匹配一個

%n

這裏的 n 可以從 1 到 9; 這個條目匹配一個等於 n 號捕獲物(後面有描述)的子串

%bxy

這裏的 x 和 y 是兩個明確的字符; 這個條目匹配以 x 開始 y 結束, 且其中 x 和 y 保持 平衡 的字符串。 意思是,如果從左到右讀這個字符串,對每次讀到一個 x 就 +1 ,讀到一個 y 就 -1, 最終結束處的那個 y 是第一個記數到 0 的 y。 舉個例子,條目 %b() 可以匹配到括號平衡的表達式

%f[set]

指 邊境模式; 這個條目會匹配到一個位於 set 內某個字符之前的一個空串, 且這個位置的前一個字符不屬於 set 。 集合 set 的含義如前面所述。 匹配出的那個空串之開始和結束點的計算就看成該處有個字符 '\0' 一樣

模式 指一個模式條目的序列。 在模式最前面加上符號 '^' 將錨定從字符串的開始處做匹配。 在模式最後面加上符號 '$' 將使匹配過程錨定到字符串的結尾。 如果 '^' 和 '$' 出現在其它位置,它們均沒有特殊含義,只表示自身。

捕獲:模式可以在內部用小括號括起一個子模式; 這些子模式被稱爲 捕獲物。 當匹配成功時,由 捕獲物 匹配到的字符串中的子串被保存起來用於未來的用途。 捕獲物以它們左括號的次序來編號。 例如,對於模式 "(a*(.)%w(%s*))" , 字符串中匹配到 "a*(.)%w(%s*)" 的部分保存在第一個捕獲物中 (因此是編號 1 ); 由 "." 匹配到的字符是 2 號捕獲物, 匹配到 "%s*" 的那部分是 3 號。

作爲一個特例,空的捕獲 () 將捕獲到當前字符串的位置(它是一個數字)。 例如,如果將模式 "()aa()" 作用到字符串"flaaap" 上,將產生兩個捕獲物: 3 和 5 。

  1. 數據類型Table(表)

在 Lua 裏,table 的創建是通過"構造表達式"來完成,最簡單構造表達式是{},用來創建一個空表。也可以在表裏添加一些數據,直接初始化表:

-- 直接初始表

local tbl = {"apple", "pear", "orange", "grape"}

--打印看效果

local tbl = {"apple", "pear", "orange", "grape"}

for k, v in pairs(a) do

    print(k .. " : " .. v)

end

打印結果:

1 : apple

2 : pear

3 : orange

4 : grape

--

不同於其他語言的數組把 0 作爲數組的初始索引,在 Lua 裏表的默認初始索引一般以 1 開始。

Lua 中的表(table)其實是一個"關聯數組"(associative arrays),數組的索引可以是數字或者是字符串。

a = {}

a["key"] = "value"

key = 10

a[key] = 22

for k, v in pairs(a) do

    print(k .. " : " .. v)

end

打印結果:

key : value

10 : 22

 

--

泛型 for 迭代器:

泛型 for 在自己內部保存迭代函數,實際上它保存三個值:迭代函數、狀態常量、控制變量。

泛型 for 迭代器提供了集合的 key/value 對,語法格式如下:

for k, v in pairs(t) do

print(k, v)

end

上面代碼中,k, v爲變量列表;pair(t)爲表達式列表。

以上實例中我們使用了 Lua 默認提供的迭代函數 ipairs。

下面我們看看泛型 for 的執行過程:

首先,初始化,計算in後面表達式的值,表達式應該返回泛型 for 需要的三個值:迭代函數、狀態常量、控制變量;與多值賦值一樣,如果表達式返回的結果個數不足三個會自動用nil補足,多出部分會被忽略。

第二,將狀態常量和控制變量作爲參數調用迭代函數(注意:對於for結構來說,狀態常量沒有用處,僅僅在初始化時獲取他的值並傳遞給迭代函數)。

第三,將迭代函數返回的值賦給變量列表。

第四,如果返回的第一個值爲nil循環結束,否則執行循環體。

第五,回到第二步再次調用迭代函數。

三、Tips。

將代碼保存爲wifi_light.lua,下載到ESP中,如果想上電就運行這個程序,可以在第一課的init.lua文件中加上紅色標註的代碼:

--本程序爲初始化程序init.lua,ESP8266上電後會默認從此程序開始運行。

--

--

--開發板上藍色小燈閃爍3下,表明程序已經運行,調試收到信息“success”

gpio.mode(0,gpio.OUTPUT)

for i = 1, 3 ,1 do

    gpio.write(0,gpio.LOW)

    --tmr.delay(s)中s單位爲微秒,1000000微秒=1秒

    tmr.delay(500000)

    gpio.write(0,gpio.HIGH)

    tmr.delay(500000)

end

print("success","\n")

--運行子程序

--內網控制LED程序。

dofile("wifi_light.lua")


  • 使用遠程控制。

1、ESP上電後配置好wifi連接之後就調用print(wifi.sta.getip()),由於連接上路由器需要一定的時間,因此,在小燈閃過三次,控制檯顯示success後,print(wifi.sta.getip())會打印出字符串nil,意思是沒有獲取到ip的信息。這時,就需要我們重新獲取了。

等待幾秒鐘,待ESP成功連接路由器後,在開發軟件的右下角,向ESP發送單條命令print(wifi.sta.getip())。得到返回信息,如果是nil,過幾秒後再嘗試,直到看到需要的信息。

 

返回的信息“192.168.100.130  255.255.255.0 192.168.100.1”中:

192.168.100.130爲ESP的IP地址,255.255.255.0爲子網掩碼,

192.168.100.1爲網關。

2、打開瀏覽器(手機瀏覽器、電腦瀏覽器均可),保證打開瀏覽器的設備與ESP連接的是同一個路由器。輸入ESP的IP地址(即192.168.100.130),我們配置的簡單服務器將顯示出來。

3、點擊按鈕ON,開發板上的小燈將亮起。

   點擊按鈕OFF,開發板上的小燈將熄滅。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章