前言
提示:這里可以添加本文要記錄的大概內(nèi)容:
例如:隨著人工智能的不斷發(fā)展,機器學習這門技術(shù)也越來越重要,很多人都開啟了學習機器學習,本文就介紹了機器學習的基礎(chǔ)內(nèi)容。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、ESP8266開發(fā)板詳解
1.引腳圖
????????NodeMCU上的D2引腳引出ESP8266芯片的GPIO4引腳
????????即digitalWrite(D2,HIGH);等價于digitalWrite(4,HIGH);
????????D開頭的是數(shù)字引腳,A開頭的是模擬引腳(右下角的ADC引腳)
????????3V3可以為外界提供3.3V電壓,Vin為NodeMCU供電(也可以用數(shù)據(jù)線供電)
????????數(shù)字引腳為3.3V,digitalWrite(D2,HIGH);即是將D2引腳置為3.3V.而digitalRead(D2);
????????引腳所連電壓不能超過3.3V。
????????模擬引腳可讀電壓范圍為0-1V。
????????USB下載串口占用的是RX和TX(GPIO3和GPIO1)
????????藍底黑字都是通訊端口(如GPIO3、GPIO1等)
????????黑底白字都是NodeMCU操作內(nèi)部存儲單元的引腳(如GPIO6、GPIO15等)
????????注意:GPIO6-GPIO11不要使用
二、互聯(lián)網(wǎng)基礎(chǔ)
1.TCP/IP協(xié)議族
????????1.鏈路層的主要作用是實現(xiàn)設(shè)備之間的物理鏈接,如WiFi
????????2.網(wǎng)絡(luò)層為網(wǎng)絡(luò)設(shè)備提供地址——IP協(xié)議
????????
????????IP協(xié)議分為IPV4和IPV6,IPV4由4個十進制數(shù)(0~255)組成
? ? ? ? 默認網(wǎng)關(guān)即WiFi路由器的IP地址
? ? ? ? 子網(wǎng)掩碼用來區(qū)分IP地址的子網(wǎng)地址與機器本身地址
? ? ? ? 參考:互聯(lián)網(wǎng)知識基礎(chǔ)-網(wǎng)絡(luò)層(第2章 – 第3節(jié)) – 太極創(chuàng)客 (taichi-maker.com)
? ? ? ? 而IPV6由8組16進制數(shù)組成,可以為更多網(wǎng)絡(luò)設(shè)備提供獨立的IP地址
? ? ? ? 3.傳輸層——TCP協(xié)議
? ? ? ????????? TCP協(xié)議特點:穩(wěn)
? ? ? ????????? ·可保證所有數(shù)據(jù)都能被接收端接收
? ? ????????? ? ·數(shù)據(jù)的傳輸順序不會被打亂
? ????????? ? ? ·傳輸數(shù)據(jù)如有損壞則重發(fā)受損數(shù)據(jù)
? ????????? ? ? 適用于電子郵件、文件傳輸?shù)阮I(lǐng)域
????????傳輸層——UDP協(xié)議
????????????????UDP協(xié)議特點:快
????????????????·UDP比TCP速度快
????????????????·不保證所有數(shù)據(jù)都能被接收端接收
????????????????·數(shù)據(jù)一旦受損,UDP協(xié)議將拋棄受損數(shù)據(jù)
? ? ? ? ? ? ? ? ·傳輸數(shù)據(jù)如有損壞不會重發(fā)受損數(shù)據(jù)
? ? ? ? ? ? ? ? 適用于在線語音/視頻、網(wǎng)游等領(lǐng)域
? ? ? ? 4.應(yīng)用層
? ? ? ? ? ? ? ? 最常用HTTP協(xié)議,HTTP協(xié)議由請求和響應(yīng)組成,類似于一問一答,具體參考:互聯(lián)網(wǎng)知識基礎(chǔ)-應(yīng)用層(第2章 – 第5節(jié)) – 太極創(chuàng)客 (taichi-maker.com)
????????請求
????????響應(yīng)
2.ESP8266工作模式
1.AP(Access Point)模式(接入點模式)類似于手機熱點
2.無線終端模式(Wireless Station)
3.混合模式
三、ESP8266接入點模式及無線終端模式
1.接入點模式代碼
3-1-3 NodeMCU開發(fā)板的接入點模式 – 太極創(chuàng)客 (taichi-maker.com)
/*
NodeMCU接入點模式
By 太極創(chuàng)客(http://www.taichi-maker.com)
2019-03-11
此程序用于演示如何將NodeMCU以接入點模式工作。通過此程序,您可以使用
電腦或者手機連接NodeMCU所建立WiFi網(wǎng)絡(luò)。
網(wǎng)絡(luò)名: taichi-maker
密碼:12345678
如需獲得更多關(guān)于如何使用NodeMCU開發(fā)物聯(lián)網(wǎng)的教程和資料信息
請參考太極創(chuàng)客網(wǎng)站(http://www.taichi-maker.com)
并在首頁搜索欄中搜索關(guān)鍵字:物聯(lián)網(wǎng)
*/
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi庫
const char *ssid = "taichi-maker"; // 這里定義將要建立的WiFi名稱。此處以"taichi-maker"為示例
// 您可以將自己想要建立的WiFi名稱填寫入此處的雙引號中
const char *password = "12345678"; // 這里定義將要建立的WiFi密碼。此處以12345678為示例
// 您可以將自己想要使用的WiFi密碼放入引號內(nèi)
// 如果建立的WiFi不要密碼,則在雙引號內(nèi)不要填入任何信息
void setup() {
Serial.begin(9600); // 啟動串口通訊
WiFi.softAP(ssid, password); // 此語句是重點。WiFi.softAP用于啟動NodeMCU的AP模式。
// 括號中有兩個參數(shù),ssid是WiFi名。password是WiFi密碼。
// 這兩個參數(shù)具體內(nèi)容在setup函數(shù)之前的位置進行定義。
Serial.print("Access Point: "); // 通過串口監(jiān)視器輸出信息
Serial.println(ssid); // 告知用戶NodeMCU所建立的WiFi名
Serial.print("IP address: "); // 以及NodeMCU的IP地址
Serial.println(WiFi.softAPIP()); // 通過調(diào)用WiFi.softAPIP()可以得到NodeMCU的IP地址
}
void loop() {
}
2.無線終端模式代碼
3-1-4 NodeMCU開發(fā)板的無線終端模式 – 太極創(chuàng)客 (taichi-maker.com)
/*
NodeMCU無線終端模式連接WiFi
By 太極創(chuàng)客(http://www.taichi-maker.com)
2019-03-11
本示例程序用于演示如何使用NodeMCU無線終端模式連接WiFi
如需獲得更多關(guān)于如何使用NodeMCU開發(fā)物聯(lián)網(wǎng)的教程和資料信息
請參考太極創(chuàng)客網(wǎng)站(http://www.taichi-maker.com)
并在首頁搜索欄中搜索關(guān)鍵字:物聯(lián)網(wǎng)
*/
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi庫
const char* ssid = "taichi-maker"; // 連接WiFi名(此處使用taichi-maker為示例)
// 請將您需要連接的WiFi名填入引號中
const char* password = "12345678"; // 連接WiFi密碼(此處使用12345678為示例)
// 請將您需要連接的WiFi密碼填入引號中
void setup() {
Serial.begin(9600); // 啟動串口通訊
WiFi.begin(ssid, password); // 啟動網(wǎng)絡(luò)連接
Serial.print("Connecting to "); // 串口監(jiān)視器輸出網(wǎng)絡(luò)連接信息
Serial.print(ssid); Serial.println(" ..."); // 告知用戶NodeMCU正在嘗試WiFi連接
int i = 0; // 這一段程序語句用于檢查WiFi是否連接成功
while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函數(shù)的返回值是由NodeMCU的WiFi連接狀態(tài)所決定的。
delay(1000); // 如果WiFi連接成功則返回值為WL_CONNECTED
Serial.print(i++); Serial.print(' '); // 此處通過While循環(huán)讓NodeMCU每隔一秒鐘檢查一次WiFi.status()函數(shù)返回值
} // 同時NodeMCU將通過串口監(jiān)視器輸出連接時長讀秒。
// 這個讀秒是通過變量i每隔一秒自加1來實現(xiàn)的。
Serial.println(""); // WiFi連接成功后
Serial.println("Connection established!"); // NodeMCU將通過串口監(jiān)視器輸出"連接成功"信息。
Serial.print("IP address: "); // 同時還將輸出NodeMCU的IP地址。這一功能是通過調(diào)用
Serial.println(WiFi.localIP()); // WiFi.localIP()函數(shù)來實現(xiàn)的。該函數(shù)的返回值即NodeMCU的IP地址。
}
void loop() {
}
四、 建立基本網(wǎng)絡(luò)服務(wù)器
1.建立基本網(wǎng)絡(luò)服務(wù)器
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : 3_2_1_First_Web_Server
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO朔
日期/Date(YYYYMMDD) : 20191107
程序目的/Purpose : 使用NodeMCU建立基本服務(wù)器。用戶可通過瀏覽器使用8266的IP地址
訪問8266所建立的基本網(wǎng)頁(Hello from ESP8266)
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
***********************************************************************/
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi庫
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti庫
#include <ESP8266WebServer.h> // ESP8266WebServer庫
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti對象,對象名稱是'wifiMulti'
ESP8266WebServer esp8266_server(80);// 建立ESP8266WebServer對象,對象名稱為esp8266_server
// 括號中的數(shù)字是網(wǎng)路服務(wù)器響應(yīng)http請求的端口號
// 網(wǎng)絡(luò)服務(wù)器標準http端口號為80,因此這里使用80為端口號
void setup(void){
Serial.begin(9600); // 啟動串口通訊
//通過addAp函數(shù)存儲 WiFi名稱 WiFi密碼
wifiMulti.addAP("RFID", "rfid&iot0243");
wifiMulti.addAP("taichi-maker", "12345678"); // 這三條語句通過調(diào)用函數(shù)addAP來記錄3個不同的WiFi網(wǎng)絡(luò)信息。
wifiMulti.addAP("taichi-maker2", "87654321"); // 這3個WiFi網(wǎng)絡(luò)名稱分別是taichi-maker, taichi-maker2, taichi-maker3。
wifiMulti.addAP("taichi-maker3", "13572468"); // 這3個網(wǎng)絡(luò)的密碼分別是123456789,87654321,13572468。
// 此處WiFi信息只是示例,請在使用時將需要連接的WiFi信息填入相應(yīng)位置。
// 另外這里只存儲了3個WiFi信息,您可以存儲更多的WiFi信息在此處。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此處的wifiMulti.run()是重點。通過wifiMulti.run(),NodeMCU將會在當前
delay(1000); // 環(huán)境中搜索addAP函數(shù)所存儲的WiFi。如果搜到多個存儲的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 將會連接信號最強的那一個WiFi信號。
} // 一旦連接WiFI成功,wifiMulti.run()將會返回“WL_CONNECTED”。這也是
// 此處while循環(huán)判斷是否跳出循環(huán)的條件。
// WiFi連接成功后將通過串口監(jiān)視器輸出連接成功信息
Serial.println('\n'); // WiFi連接成功后
Serial.print("Connected to "); // NodeMCU將通過串口監(jiān)視器輸出。
Serial.println(WiFi.SSID()); // 連接的WiFI名稱
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
//--------"啟動網(wǎng)絡(luò)服務(wù)功能"程序部分開始-------- // 此部分為程序為本示例程序重點1
esp8266_server.begin(); // 詳細講解請參見太極創(chuàng)客網(wǎng)站《零基礎(chǔ)入門學用物聯(lián)網(wǎng)》
esp8266_server.on("/", handleRoot); // 第3章-第2節(jié) ESP8266-NodeMCU網(wǎng)絡(luò)服務(wù)器-1
esp8266_server.onNotFound(handleNotFound);
//--------"啟動網(wǎng)絡(luò)服務(wù)功能"程序部分結(jié)束--------
Serial.println("HTTP esp8266_server started");// 告知用戶ESP8266網(wǎng)絡(luò)服務(wù)功能已經(jīng)啟動
}
/* 以下函數(shù)語句為本示例程序重點3
詳細講解請參見太極創(chuàng)客網(wǎng)站《零基礎(chǔ)入門學用物聯(lián)網(wǎng)》
第3章-第2節(jié) 3_2_1_First_Web_Server 的說明講解*/
void loop(void){
esp8266_server.handleClient(); // 處理http服務(wù)器訪問(檢查是否有瀏覽器請求網(wǎng)頁信息)
}
/* 以下兩個函數(shù)為本示例程序重點2
詳細講解請參見太極創(chuàng)客網(wǎng)站《零基礎(chǔ)入門學用物聯(lián)網(wǎng)》
第3章-第2節(jié) 3_2_1_First_Web_Server 的說明講解*/
void handleRoot() { //處理網(wǎng)站根目錄“/”的訪問請求
esp8266_server.send(200, "text/plain", "臭婆娘~ o(* ̄▽ ̄*)o這招你會不會捏"); // NodeMCU將調(diào)用此函數(shù)。
}
// 設(shè)置處理404情況的函數(shù)'handleNotFound'
void handleNotFound(){ // 當瀏覽器請求的網(wǎng)絡(luò)資源無法在服務(wù)器找到時,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU將調(diào)用此函數(shù)。
}
2.通過網(wǎng)絡(luò)服務(wù)實現(xiàn)NodeMCU開發(fā)板基本控制
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : 3_2_2_Turning_on_and_off_an_LED
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO朔
日期/Date(YYYYMMDD) : 20191108
程序目的/Purpose : 使用NodeMCU建立基本服務(wù)器。用戶可通過瀏覽器使用8266的IP地址
訪問8266所建立的基本網(wǎng)頁并通過該頁面點亮/熄滅NodeMCU的內(nèi)置LED
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
***********************************************************************/
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi庫
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti庫
#include <ESP8266WebServer.h> // ESP8266WebServer庫
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti對象,對象名稱是 'wifiMulti'
ESP8266WebServer esp8266_server(80);// 建立網(wǎng)絡(luò)服務(wù)器對象,該對象用于響應(yīng)HTTP請求。監(jiān)聽端口(80)
void setup(void){
Serial.begin(9600); // 啟動串口通訊
pinMode(LED_BUILTIN, OUTPUT); //設(shè)置內(nèi)置LED引腳為輸出模式以便控制LED
wifiMulti.addAP("RFID", "rfid&iot0243");
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); // 將需要連接的一系列WiFi ID和密碼輸入這里
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); // ESP8266-NodeMCU再啟動后會掃描當前網(wǎng)絡(luò)
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 環(huán)境查找是否有這里列出的WiFi ID。如果有
Serial.println("Connecting ..."); // 則嘗試使用此處存儲的密碼進行連接。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此處的wifiMulti.run()是重點。通過wifiMulti.run(),NodeMCU將會在當前
delay(1000); // 環(huán)境中搜索addAP函數(shù)所存儲的WiFi。如果搜到多個存儲的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 將會連接信號最強的那一個WiFi信號。
} // 一旦連接WiFI成功,wifiMulti.run()將會返回“WL_CONNECTED”。這也是
// 此處while循環(huán)判斷是否跳出循環(huán)的條件。
// WiFi連接成功后將通過串口監(jiān)視器輸出連接成功信息
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID()); // 通過串口監(jiān)視器輸出連接的WiFi名稱
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // 通過串口監(jiān)視器輸出ESP8266-NodeMCU的IP
esp8266_server.begin(); // 啟動網(wǎng)站服務(wù)
esp8266_server.on("/", HTTP_GET, handleRoot); // 設(shè)置服務(wù)器根目錄即'/'的函數(shù)'handleRoot'
/*當有瀏覽器請求首頁"/"并且方法是HTTP_GET時,才調(diào)用handleRoot*/
esp8266_server.on("/LED", HTTP_POST, handleLED); // 設(shè)置處理LED控制請求的函數(shù)'handleLED'
/*當有瀏覽器請求頁面"/LED"并且方法是HTTP_POST時,才調(diào)用handleLED*/
esp8266_server.onNotFound(handleNotFound); // 設(shè)置處理404情況的函數(shù)'handleNotFound'
Serial.println("HTTP esp8266_server started");// 告知用戶ESP8266網(wǎng)絡(luò)服務(wù)功能已經(jīng)啟動
}
void loop(void){
esp8266_server.handleClient(); // 檢查http服務(wù)器訪問
}
/*設(shè)置服務(wù)器根目錄即'/'的函數(shù)'handleRoot'
該函數(shù)的作用是每當有客戶端訪問NodeMCU服務(wù)器根目錄時,
NodeMCU都會向訪問設(shè)備發(fā)送 HTTP 狀態(tài) 200 (Ok) 這是send函數(shù)的第一個參數(shù)。
同時NodeMCU還會向瀏覽器發(fā)送HTML代碼,以下示例中send函數(shù)中第三個參數(shù),
也就是雙引號中的內(nèi)容就是NodeMCU發(fā)送的HTML代碼。該代碼可在網(wǎng)頁中產(chǎn)生LED控制按鈕。
當用戶按下按鈕時,瀏覽器將會向NodeMCU的/LED頁面發(fā)送HTTP請求,請求方式為POST。
NodeMCU接收到此請求后將會執(zhí)行handleLED函數(shù)內(nèi)容*/
void handleRoot() {
esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");
}
/*html——超文本標記語言
<form action=\"/LED\" method=\"POST\">
<input type=\"submit\" value=\"Toggle LED\">
</form>
form為表單格式,其中劃出一個名為Toggle LED的按鍵,按下后,會以POST方式跳轉(zhuǎn)到/LED頁面
*/
//處理LED控制請求的函數(shù)'handleLED'
void handleLED() {
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// 改變LED的點亮或者熄滅狀態(tài),翻轉(zhuǎn)IO口
esp8266_server.sendHeader("Location","/"); // 跳轉(zhuǎn)回頁面根目錄(首頁)
esp8266_server.send(303); // 發(fā)送Http相應(yīng)代碼303 跳轉(zhuǎn)
}
// 設(shè)置處理404情況的函數(shù)'handleNotFound'
void handleNotFound(){
esp8266_server.send(404, "text/plain", "404: Not found"); // 發(fā)送 HTTP 狀態(tài) 404 (未找到頁面) 并向瀏覽器發(fā)送文字 "404: Not found"
}
3.通過網(wǎng)絡(luò)服務(wù)將開發(fā)板引腳狀態(tài)顯示在網(wǎng)頁中
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : 3_2_4_Pin_State_Display_Auto_Refresh
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO朔
日期/Date(YYYYMMDD) : 20200128
程序目的/Purpose : 使用NodeMCU建立基本服務(wù)器。該網(wǎng)頁將顯示引腳D3狀態(tài)。同時狀態(tài)會
每隔5秒鐘更新一次。
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
***********************************************************************/
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi庫
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti庫
#include <ESP8266WebServer.h> // ESP8266WebServer庫
#define buttonPin 0 // 按鈕引腳D3(GPIO0)因為它已經(jīng)與開發(fā)板上的FLASH按鍵開關(guān)連接好了。
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti對象,對象名稱是'wifiMulti'
ESP8266WebServer esp8266_server(80);// 建立網(wǎng)絡(luò)服務(wù)器對象,該對象用于響應(yīng)HTTP請求。監(jiān)聽端口(80)
bool pinState; // 存儲引腳狀態(tài)用變量
void setup(){
Serial.begin(9600); // 啟動串口通訊
delay(10);
Serial.println("");
pinMode(buttonPin, INPUT_PULLUP); // 將按鍵引腳設(shè)置為輸入上拉模式
wifiMulti.addAP("RFID", "rfid&iot0243");
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); // 將需要連接的一系列WiFi ID和密碼輸入這里
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); // ESP8266-NodeMCU在啟動后會掃描當前網(wǎng)絡(luò)
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 環(huán)境查找是否有這里列出的WiFi ID。如果有
Serial.println("Connecting ..."); // 則嘗試使用此處存儲的密碼進行連接。
// 另外這里只存儲了3個WiFi信息,您可以存儲更多
// 的WiFi信息在此處。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此處的wifiMulti.run()是重點。通過wifiMulti.run(),NodeMCU將會在當前
delay(1000); // 環(huán)境中搜索addAP函數(shù)所存儲的WiFi。如果搜到多個存儲的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 將會連接信號最強的那一個WiFi信號。
} // 一旦連接WiFI成功,wifiMulti.run()將會返回“WL_CONNECTED”。這也是
// 此處while循環(huán)判斷是否跳出循環(huán)的條件。
// WiFi連接成功后將通過串口監(jiān)視器輸出連接成功信息
Serial.println('\n'); // WiFi連接成功后
Serial.print("Connected to "); // NodeMCU將通過串口監(jiān)視器輸出。
Serial.println(WiFi.SSID()); // 連接的WiFI名稱
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
esp8266_server.begin();
esp8266_server.on("/", handleRoot);
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started");// 告知用戶ESP8266網(wǎng)絡(luò)服務(wù)功能已經(jīng)啟動
}
void loop(){
esp8266_server.handleClient(); // 處理http服務(wù)器訪問
pinState = digitalRead(buttonPin); // 獲取引腳狀態(tài)
}
/* 以下函數(shù)處理網(wǎng)站首頁的訪問請求。此函數(shù)為本示例程序重點1
詳細講解請參見太極創(chuàng)客網(wǎng)站《零基礎(chǔ)入門學用物聯(lián)網(wǎng)》
第3章-第2節(jié)“通過網(wǎng)絡(luò)服務(wù)將開發(fā)板引腳狀態(tài)顯示在網(wǎng)頁中”的說明講解。*/
void handleRoot() { //處理網(wǎng)站目錄“/”的訪問請求
esp8266_server.send(200, "text/html", sendHTML(pinState));
}
/*
建立用于發(fā)送給客戶端瀏覽器的HTML代碼。此代碼將會每隔5秒刷新頁面。
通過頁面刷新,引腳的最新狀態(tài)也會顯示于頁面中
*/
String sendHTML(bool buttonState){
String htmlCode = "<!DOCTYPE html> <html>\n";
htmlCode +="<head><meta http-equiv='refresh' content='5'/>\n";//每隔5s自動刷新一次
htmlCode +="<title>ESP8266 Butoon State</title>\n";
htmlCode +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
htmlCode +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
htmlCode +="</style>\n";
htmlCode +="</head>\n";
htmlCode +="<body>\n";
htmlCode +="<h1>ESP8266 BUTTON STATE</h1>\n";
if(buttonState)
{htmlCode +="<p>Button Status: HIGH</p>\n";}
else
{htmlCode +="<p>Button Status: LOW</p>\n";}
htmlCode +="</body>\n";
htmlCode +="</html>\n";
return htmlCode;
}
// 設(shè)置處理404情況的函數(shù)'handleNotFound'
void handleNotFound(){ // 當瀏覽器請求的網(wǎng)絡(luò)資源無法在服務(wù)器找到時,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU將調(diào)用此函數(shù)。
}
五、ESP8266閃存文件系統(tǒng)
ESP8266閃存文件系統(tǒng)基本操作
1.ESP8266閃存文件系統(tǒng)大小
? ? ? ? 大小一般為4MB,具體以生產(chǎn)商為準,可以從Arduino IDE中讀取
? ? ? ? 若程序使用了Flash,需配置一下Flash Size
2.通過程序向閃存文件系統(tǒng)寫入信息
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-write
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20191109
程序目的/Purpose : 此程序用于演示如何向NodeMCU的SPIFFS中建立名為
notes.txt的文件,程序還將向該文件寫入信息。
-----------------------------------------------------------------------
函數(shù)說明:
SPIFFS.open(file_name, "w");
以上函數(shù)有兩個參數(shù):
第一個參數(shù)是被操作的文件名稱,本示例中該文件為/notes.txt
第二個參數(shù)"w" 代表寫入文件信息。(如需了解如何讀取信息,請參閱示例程序esp8266-flash-read)
***********************************************************************/
#include <FS.h>//包含閃存的一些函數(shù)
String file_name = "/taichi-maker/notes.txt"; //被讀取的文件位置和名稱
void setup() {
Serial.begin(9600);
Serial.println("");
Serial.println("SPIFFS format start");
SPIFFS.format(); // 格式化SPIFFS(Serial Peripheral Interface Flash File System)閃存文件系統(tǒng)
Serial.println("SPIFFS format finish");
if(SPIFFS.begin()){ // 啟動SPIFFS
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
File dataFile = SPIFFS.open(file_name, "w");// 建立File對象用于向SPIFFS中的file對象(即/notes.txt)寫入信息
dataFile.println("Hello IOT World."); // 向dataFile寫入字符串信息
dataFile.close(); // 完成文件寫入后關(guān)閉文件
Serial.println("Finished Writing data to SPIFFS");
}
void loop() {
}
3. 通過程序從閃存文件系統(tǒng)讀取信息
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-read
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20191109
程序目的/Purpose : 此程序用于演示如何從NodeMCU的內(nèi)置SPIFFS中存儲的文件notes.txt讀取數(shù)據(jù)。
notes.txt 文件內(nèi)容將會通過串口監(jiān)視器顯示出來供用戶確認。
注意在使用本程序以前需要先將notes.txt 文件上傳到NodeMCU開發(fā)板的SPIFFS中
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
-----------------------------------------------------------------------
函數(shù)說明:
SPIFFS.open(file_name, "r");
以上SPIFFS函數(shù)有兩個參數(shù):
第一個參數(shù)是被操作的文件名稱,本示例中該文件為/notes.txt
第二個參數(shù)"r" 代表讀取文件信息。(如需了解如何寫入信息,請參閱示例程序esp8266-flash-write)
***********************************************************************/
#include <FS.h>
String file_name = "/taichi-maker/notes.txt"; //被讀取的文件位置和名稱
void setup() {
Serial.begin(9600);
Serial.println("");
if(SPIFFS.begin()){ // 啟動閃存文件系統(tǒng)
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
//確認閃存中是否有file_name文件
if (SPIFFS.exists(file_name)){
Serial.print(file_name);
Serial.println(" FOUND.");
} else {
Serial.print(file_name);
Serial.print(" NOT FOUND.");
}
//建立File對象用于從SPIFFS中讀取文件
File dataFile = SPIFFS.open(file_name, "r");
//讀取文件內(nèi)容并且通過串口監(jiān)視器輸出文件信息
for(int i=0; i<dataFile.size(); i++){
Serial.print((char)dataFile.read());
}
//完成文件讀取后關(guān)閉文件
dataFile.close();
}
void loop() {
}
4. 通過程序向閃存文件系統(tǒng)文件添加信息
? ? ? ? 使用"a"會從文件尾部開始寫,而"w"操作將會在文件系統(tǒng)中建立該文件。如果文件系統(tǒng)有該文件,則程序?qū)匦陆⒃撐募?,即原有文件信息將會被覆蓋。
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-append
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20191109
程序目的/Purpose : 此程序用于演示如何向NodeMCU的內(nèi)置SPIFFS中存儲的文件
notes.txt添加數(shù)據(jù)。
-----------------------------------------------------------------------
函數(shù)說明:
SPIFFS.open(file_name, "a");
以上SPIFFS函數(shù)有兩個參數(shù):
第一個參數(shù)是被操作的文件名稱,本示例中該文件為/notes.txt
第二個參數(shù)"a" 代表添加文件信息。(如需了解如何讀取信息,請參閱示例程序esp8266-flash-read)
此示例程序所演示的是向SPIFFS中的文件里添加信息。這一操作寫入信息有所區(qū)別。
添加信息是不會刪除文件內(nèi)原有信息,而是在原有信息后面添加新的信息。
但寫入操作(示例 esp8266-flash-write.ino)是將文件內(nèi)容完全清除,重新寫入新信息。
***********************************************************************/
#include <FS.h>
String file_name = "/taichi-maker/notes.txt"; //被讀取的文件位置和名稱
void setup() {
Serial.begin(9600);
Serial.println("");
if(SPIFFS.begin()){ // 啟動閃存文件系統(tǒng)
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
//確認閃存中是否有file_name文件
if (SPIFFS.exists(file_name)){
Serial.print(file_name);
Serial.println(" FOUND.");
File dataFile = SPIFFS.open(file_name, "a");// 建立File對象用于向SPIFFS中的file對象(即/notes.txt)寫入信息 "a"即Append
dataFile.println("This is Appended Info."); // 向dataFile添加字符串信息
dataFile.close(); // 完成文件操作后關(guān)閉文件
Serial.println("Finished Appending data to SPIFFS");
} else {
Serial.print(file_name);
Serial.print(" NOT FOUND.");
}
}
void loop() {
}
5. 通過程序讀取目錄內(nèi)容(讀取文件夾中所包含文件)
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-folder-read
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20191109
程序目的/Purpose : 此程序用于演示如何從NodeMCU的內(nèi)置SPIFFS中文件夾里讀取文件信息
文件夾內(nèi)容將會通過串口監(jiān)視器顯示出來。
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
-----------------------------------------------------------------------
函數(shù)說明:
SPIFFS.openDir(folder_name);
以上函數(shù)打開指定目錄并返回一個目錄對象實例。
***********************************************************************/
#include <FS.h>
String file_name = "/taichi-maker/myFile.txt"; //被讀取的文件位置和名稱
String folder_name = "/taichi-maker"; //被讀取的文件夾
void setup() {
Serial.begin(9600);
Serial.println("");
if(SPIFFS.begin()){ // 啟動閃存文件系統(tǒng)
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
File dataFile = SPIFFS.open(file_name, "w");// 建立File對象用于向SPIFFS中的file對象(即myFile.txt)寫入信息
dataFile.println("Hello Taichi-Maker."); // 向dataFile寫入字符串信息
dataFile.close(); // 完成文件寫入后關(guān)閉文件
Serial.println(F("Finished Writing data to SPIFFS"));
/*添加 F() 相當于為字符串常量定義了PROGMEM屬性,常量字符串仍然存儲在FLASH中,
但是程序運行時不會再將常量字符串從FLASH中copy到SRAM中,
而是直接讀取FLASH中的字符串,這樣一來就節(jié)約了SRAM,但是代碼運行速度就下降了。*/
// 顯示目錄中文件內(nèi)容以及文件大小
Dir dir = SPIFFS.openDir(folder_name); // 建立“目錄”對象 dir=folder_name="/taichi-maker"
while (dir.next()) { // dir.next()用于檢查目錄中是否還有“下一個文件”
Serial.println(dir.fileName()); // 輸出文件名
}
}
void loop() {
}
6. 從閃存文件系統(tǒng)中刪除文件
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-remove
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20191109
程序目的/Purpose : 此程序用于演示如何刪除SPIFFS中存儲的文件
***********************************************************************/
#include <FS.h>
String file_name = "/taichi-maker/notes.txt"; //被讀取的文件位置和名稱
void setup() {
Serial.begin(9600);
Serial.println("");
if(SPIFFS.begin()){ // 啟動閃存文件系統(tǒng)
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
//從閃存中刪除file_name文件
if (SPIFFS.remove(file_name)){
Serial.print(file_name);
Serial.println(" remove sucess");
} else {
Serial.print(file_name);
Serial.println(" remove fail");
}
}
void loop() {
}
7. 顯示閃存文件系統(tǒng)信息
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : esp8266-flash-info
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO 朔
日期/Date(YYYYMMDD) : 20200204
程序目的/Purpose : 此程序用于演示如何使用FSInfo對象來顯示閃存文件系統(tǒng)狀態(tài)
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
***********************************************************************/
#include <FS.h>
FSInfo fs_info;
void setup() {
Serial.begin(9600);
SPIFFS.begin(); //啟動SPIFFS
Serial.println("");
Serial.println("SPIFFS Started.");
// 閃存文件系統(tǒng)信息
SPIFFS.info(fs_info);
// 可用空間總和(單位:字節(jié))
Serial.print("totalBytes: ");
Serial.print(fs_info.totalBytes);
Serial.println(" Bytes");
// 已用空間(單位:字節(jié))
Serial.print("usedBytes: ");
Serial.print(fs_info.usedBytes);
Serial.println(" Bytes");
// 最大文件名字符限制(含路徑和'\0')
Serial.print("maxPathLength: ");
Serial.println(fs_info.maxPathLength);
// 最多允許打開文件數(shù)量
Serial.print("maxOpenFiles: ");
Serial.println(fs_info.maxOpenFiles);
// 存儲塊大小
Serial.print("blockSize: ");
Serial.println(fs_info.blockSize);
// 存儲頁大小
Serial.print("pageSize: ");
Serial.println(fs_info.pageSize);
}
void loop() {
}
8.通過Arduino IDE向閃存文件系統(tǒng)上傳文件
????????將需要上傳的文件保存在程序路徑下的data文件夾中
????????根據(jù)所要上傳的文件大小調(diào)整Flash Size大小?
六、使用閃存文件系統(tǒng)建立功能更加豐富的網(wǎng)絡(luò)服務(wù)器
- 在網(wǎng)頁中加載閃存文件系統(tǒng)中的圖片、CSS和JavaScript
- 通過網(wǎng)頁控制ESP8266開發(fā)板的引腳
- 通過網(wǎng)頁文本框控制ESP8266開發(fā)板的PWM引腳
- (Ajax)控制LED引腳并將A0引腳讀數(shù)實時顯示于網(wǎng)頁中
- (JavaScript)通過網(wǎng)頁圖形界面控制ESP8266的PWM引腳
- (JavaScript)使用指針表顯示模擬輸入引腳數(shù)值
- 通過網(wǎng)頁將文件上傳到ESP8266開發(fā)板閃存文件系統(tǒng)
七、ESP8266幫助文檔
1.
ESP8266-Arduino庫 開發(fā)參考資料 – 太極創(chuàng)客 (taichi-maker.com)
注意書寫格式,如GET / HTTP中間的空格?
?在http請求時,我們一般會在request header 或 response header 中看到”Connection:Keep-Alive”或 “Connection:close”,這里具體的含義是有關(guān)http 請求的是否保持長連接,即鏈接是否復(fù)用,每次請求是復(fù)用已建立好的請求,還是重新建立一個新的請求。
響應(yīng)體即www.example.com的網(wǎng)頁信息
2.
客戶端向服務(wù)器發(fā)送數(shù)據(jù)信息
GET即可以用來發(fā)送信息也可以用來請求信息?
3.
客戶端向服務(wù)器請求數(shù)據(jù)信息
七、JSON
size_t? 相當于? unsigned long
?
?效果如下
?
這樣也打印的是123
String jsonCode = "{\"info\": {\"name\": \"taichimaker\",\"url\": \"www.taichi-maker.com\",\"email\": \"taichimaker@163.com\"},\"digital_pin\": {\"d1\": \"";
jsonCode += String(digitalRead(D1));
jsonCode += "\",\"d2\": \"";
jsonCode += String(digitalRead(D2));
jsonCode += "\",\"d3\": \"";
jsonCode += String(digitalRead(D3));
jsonCode += "\"},\"analog_pin\": {\"a0\": \"";
jsonCode += String(analogRead(A0));
jsonCode += "\"}}";
合成后如下
{
"info": {
"name": "taichimaker",
"url": "www.taichi-maker.com",
"email": "taichimaker@163.com"
},
"digital_pin": {
"d1": "1",
"d2": "0",
"d3": "1"
},
"analog_pin": {
"a0": "500"
}
}
Json建立過程?
{
"info": {
"name": "taichimaker",
"url": "www.taichi-maker.com",
"email": "taichimaker@163.com"
},
"digital_pin": {
"d1": "1",
"d2": "0",
"d3": "1"
},
"analog_pin": {
"a0": "500"
}
}
該段Json代碼有兩種建立方式
1.手動建立
String rootJson(){
String jsonCode = "{\"info\": {\"name\": \"taichimaker\",\"url\": \"www.taichi-maker.com\",\"email\": \"taichimaker@163.com\"},\"digital_pin\": {\"d1\": \"";
jsonCode += String(digitalRead(D1));
jsonCode += "\",\"d2\": \"";
jsonCode += String(digitalRead(D2));
jsonCode += "\",\"d3\": \"";
jsonCode += String(digitalRead(D3));
jsonCode += "\"},\"analog_pin\": {\"a0\": \"";
jsonCode += String(analogRead(A0));
jsonCode += "\"}}";
Serial.print("jsonCode: ");Serial.println(jsonCode);
return jsonCode;
}
2.使用官方工具建立(詳細步驟如下圖)
https://arduinojson.org/v5/assistant/
String rootJson(){
const size_t capacity = JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(3)+140;//
DynamicJsonDocument doc(capacity);
JsonObject info = doc.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
JsonObject digital_pin = doc.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
JsonObject analog_pin = doc.createNestedObject("analog_pin");
analog_pin["a0"] = String(analogRead(A0));
// 結(jié)束assistant的serialize代碼
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("Root Json Code: ");Serial.println(jsonCode);
return jsonCode;
}
使用官方工具建立步驟
?首先復(fù)制Serializing program中的代碼,將1,0,1,500改為識別對應(yīng)引腳的狀態(tài),capcity修改為Parsing program同樣大小,這樣運行更加穩(wěn)定,然后修改串口打印方式
單獨請求一段Json
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : cgj_server_1_serialize
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : CYNO朔
日期/Date(YYYYMMDD) : 2020517
程序目的/Purpose :
本實例用于演示esp8266的JSON數(shù)據(jù)通訊。
操作測試本程序需要使用兩臺8266開發(fā)板。其中一臺為服務(wù)器端,一臺為客戶端。
本程序為服務(wù)器程序,功能如下:
1. 實時讀取A0、 D1、D2以及D3引腳的讀數(shù)。
2. 當有客戶端請求信息時,將會通過http響應(yīng)將引腳讀數(shù)等信息發(fā)送給客戶端。
信息發(fā)送格式為JSON格式。
3. 使用ArduinoJson庫的Serialize方式建立響應(yīng)JSON信息
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
***********************************************************************/
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi庫
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti庫
#include <ESP8266WebServer.h> // ESP8266WebServer庫
#include <ArduinoJson.h> // ArduinoJson庫
#define buttonPin D3 // 按鈕引腳D3
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti對象,對象名稱是'wifiMulti'
ESP8266WebServer esp8266_server(80);// 建立網(wǎng)絡(luò)服務(wù)器對象,該對象用于響應(yīng)HTTP請求。監(jiān)聽端口(80)
IPAddress local_IP(192, 168, 3, 12); // 設(shè)置ESP8266-NodeMCU聯(lián)網(wǎng)后的IP
IPAddress gateway(192, 168, 3, 1); // 設(shè)置網(wǎng)關(guān)IP(通常網(wǎng)關(guān)IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0); // 設(shè)置子網(wǎng)掩碼
IPAddress dns(192,168,3,1); // 設(shè)置局域網(wǎng)DNS的IP(通常局域網(wǎng)DNS的IP是WiFI路由IP)
void setup(){
Serial.begin(9600); // 啟動串口通訊
Serial.println("");
// 將引腳設(shè)置為輸入上拉模式
pinMode(D1, INPUT_PULLUP);
pinMode(D2, INPUT_PULLUP);
pinMode(buttonPin, INPUT_PULLUP); // NodeMCU開發(fā)板按鍵連接在D3引腳上
// 設(shè)置開發(fā)板網(wǎng)絡(luò)環(huán)境
if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("Failed to Config ESP8266 IP");
}
//通過addAp函數(shù)存儲 WiFi名稱 WiFi密碼
wifiMulti.addAP("RFID", "rfid&iot0243"); // 這三條語句通過調(diào)用函數(shù)addAP來記錄3個不同的WiFi網(wǎng)絡(luò)信息。
wifiMulti.addAP("taichi-maker2", "87654321"); // 這3個WiFi網(wǎng)絡(luò)名稱分別是taichi-maker, taichi-maker2, taichi-maker3。
wifiMulti.addAP("taichi-maker3", "13572468"); // 這3個網(wǎng)絡(luò)的密碼分別是123456789,87654321,13572468。
// 此處WiFi信息只是示例,請在使用時將需要連接的WiFi信息填入相應(yīng)位置。
// 另外這里只存儲了3個WiFi信息,您可以存儲更多的WiFi信息在此處。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此處的wifiMulti.run()是重點。通過wifiMulti.run(),NodeMCU將會在當前
delay(1000); // 環(huán)境中搜索addAP函數(shù)所存儲的WiFi。如果搜到多個存儲的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 將會連接信號最強的那一個WiFi信號。
} // 一旦連接WiFI成功,wifiMulti.run()將會返回“WL_CONNECTED”。這也是
// 此處while循環(huán)判斷是否跳出循環(huán)的條件。
// WiFi連接成功后將通過串口監(jiān)視器輸出連接成功信息
Serial.println('\n'); // WiFi連接成功后
Serial.print("Connected to "); // NodeMCU將通過串口監(jiān)視器輸出。
Serial.println(WiFi.SSID()); // 連接的WiFI名稱
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
esp8266_server.begin();
esp8266_server.on("/", handleRoot);
esp8266_server.on("/info", handleInfo);
esp8266_server.on("/digital_pin", handleDigitalPin);
Serial.println("HTTP esp8266_server started");// 告知用戶ESP8266網(wǎng)絡(luò)服務(wù)功能已經(jīng)啟動
}
void loop(){
// 處理http服務(wù)器訪問
esp8266_server.handleClient();
}
void handleRoot() { //處理網(wǎng)站目錄“/”的訪問請求
esp8266_server.send(200, "application/json", rootJson());
}
void handleInfo(){
esp8266_server.send(200, "application/json", infoJson());
}
void handleDigitalPin(){
esp8266_server.send(200, "application/json", digitalpinJson());
}
// 實時獲取ESP8266開發(fā)板引腳信息并且建立JSON信息
// 以便ESP8266服務(wù)器通過響應(yīng)信息發(fā)送給客戶端
String rootJson(){
// 開始ArduinoJson Assistant的serialize代碼
const size_t capacity = JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(3)+140;
DynamicJsonDocument doc(capacity);
JsonObject info = doc.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
JsonObject digital_pin = doc.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
JsonObject analog_pin = doc.createNestedObject("analog_pin");
analog_pin["a0"] = String(analogRead(A0));
// 結(jié)束assistant的serialize代碼
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("Root Json Code: ");Serial.println(jsonCode);
return jsonCode;
}
//V6版本
String infoJson(){
StaticJsonDocument<128> doc;
JsonObject info = doc.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
String jsonCode;
serializeJson(doc, jsonCode);
return jsonCode;
}
String digitalpinJson(){
StaticJsonDocument<96> doc;
JsonObject digital_pin = doc.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
String jsonCode;
serializeJson(doc, jsonCode);
return jsonCode;
}
//V5版本
/*
String infoJson(){
const size_t capacity = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3)+90;
DynamicJsonBuffer jsonBuffer(capacity);
JsonObject& root = jsonBuffer.createObject();
JsonObject& info = root.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
String jsonCode;
root.printTo(jsonCode);
return jsonCode;
}
*/
/*
String digitalpinJson(){
const size_t capacity = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3)+30;
DynamicJsonBuffer jsonBuffer(capacity);
JsonObject& root = jsonBuffer.createObject();
JsonObject& digital_pin = root.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
String jsonCode;
root.printTo(jsonCode);
return jsonCode;
}
*/
ESP8266客戶端發(fā)送多種JSON數(shù)據(jù)信ddd息
/**********************************************************************
項目名稱/Project : 零基礎(chǔ)入門學用物聯(lián)網(wǎng)
程序名稱/Program name : client_send_multi_json
團隊/Team : 太極創(chuàng)客團隊 / Taichi-Maker (www.taichi-maker.com)
作者/Author : Dapenson
日期/Date(YYYYMMDD) : 20200425
程序目的/Purpose :
本實例用于演示esp8266的json數(shù)據(jù)通訊。
操作測試本程序需要使用兩臺8266開發(fā)板。其中一臺為服務(wù)器端,一臺為客戶端
本程序為客戶端程序,功能如下:
1. 實時讀取A0、 D1、D2以及D3引腳的讀數(shù)。
2. 向服務(wù)器發(fā)送多種Json信息。
3. 在有些發(fā)送的信息中包含有D3引腳狀態(tài)從而控制服務(wù)器開發(fā)板上
的LED點亮或熄滅
-----------------------------------------------------------------------
修訂歷史/Revision History
日期/Date 作者/Author 參考號/Ref 修訂說明/Revision Description
20200521 CYNO朔 001 調(diào)整以使程序與csj_client一致
-----------------------------------------------------------------------
本示例程序為太極創(chuàng)客團隊制作的《零基礎(chǔ)入門學用物聯(lián)網(wǎng)》中示例程序。
該教程為對物聯(lián)網(wǎng)開發(fā)感興趣的朋友所設(shè)計和制作。如需了解更多該教程的信息,請參考以下網(wǎng)頁:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ArduinoJson.h>
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti對象
const char* host = "192.168.3.12"; // 網(wǎng)絡(luò)服務(wù)器地址
const int httpPort = 80; // http端口80
void setup(){
Serial.begin(9600);
Serial.println("");
//通過addAp函數(shù)存儲 WiFi名稱 WiFi密碼
wifiMulti.addAP("RFID", "rfid&iot0243"); // 這三條語句通過調(diào)用函數(shù)addAP來記錄3個不同的WiFi網(wǎng)絡(luò)信息。
wifiMulti.addAP("taichi-maker2", "87654321"); // 這3個WiFi網(wǎng)絡(luò)名稱分別是taichi-maker, taichi-maker2, taichi-maker3。
wifiMulti.addAP("taichi-maker3", "13572468"); // 這3個網(wǎng)絡(luò)的密碼分別是123456789,87654321,13572468。
// 此處WiFi信息只是示例,請在使用時將需要連接的WiFi信息填入相應(yīng)位置。
// 另外這里只存儲了3個WiFi信息,您可以存儲更多的WiFi信息在此處。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此處的wifiMulti.run()是重點。通過wifiMulti.run(),NodeMCU將會在當前
delay(1000); // 環(huán)境中搜索addAP函數(shù)所存儲的WiFi。如果搜到多個存儲的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 將會連接信號最強的那一個WiFi信號。
} // 一旦連接WiFI成功,wifiMulti.run()將會返回“WL_CONNECTED”。這也是
// 此處while循環(huán)判斷是否跳出循環(huán)的條件。
// WiFi連接成功后將通過串口監(jiān)視器輸出連接成功信息
Serial.println('\n'); // WiFi連接成功后
Serial.print("Connected to "); // NodeMCU將通過串口監(jiān)視器輸出。
Serial.println(WiFi.SSID()); // 連接的WiFI名稱
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
}
void loop(){
// 發(fā)送HTTP請求,使用參數(shù)控制函數(shù)發(fā)送不同類型JSON
httpRequest(1);
delay(2000);
httpRequest(2);
delay(2000);
httpRequest(3);
delay(2000);
Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
// 向服務(wù)器發(fā)送HTTP請求,請求信息中包含json信息
void httpRequest(int jsonType){
// 建立WiFi客戶端對象,對象名稱client
WiFiClient client;
// 根據(jù)jsonType參數(shù)建立不同類型JSON
String payloadJson = buildJson(jsonType);
// 建立字符串,用于HTTP請求
String httpRequest = String("GET /") + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n" + payloadJson;
// 通過串口輸出連接服務(wù)器名稱以便查閱連接服務(wù)器的網(wǎng)址
Serial.print("Connecting to ");
Serial.print(host);
if (client.connect(host, httpPort)){
Serial.println(" Success!"); // 連接成功后串口輸出“Success”信息
client.print(httpRequest); // 向服務(wù)器發(fā)送請求
Serial.println("Sending request: "); // 通過串口輸出HTTP請求信息內(nèi)容以便查閱
Serial.println(httpRequest);
Serial.println("Web Server Response:"); // 通過串口監(jiān)視輸出服務(wù)器響應(yīng)信息
while (client.connected() || client.available()){
if (client.available()){
String line = client.readStringUntil('\n');
Serial.println(line);
}
}
} else{ // 如果連接不成功則通過串口輸出“連接失敗”信息
Serial.println(" failed!");
}
client.stop(); // 斷開與服務(wù)器的連接
Serial.print("Disconnected from "); // 并且通過串口輸出斷開連接信息
Serial.println(host);
Serial.println("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
}
//建立json信息v6
String buildJson(int type){
StaticJsonDocument<256> doc;
if (type == 1){
JsonObject info = doc.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
}
if (type == 2){
JsonObject digital_pin = doc.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
}
if (type == 3){
doc["analog_pin"]["a0"] = String(analogRead(A0));
//JsonObject analog_pin = doc.createNestedObject("analog_pin");
//analog_pin["a0"] = String(analogRead(A0));
}
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("type=");
Serial.println(type);
Serial.print("json Code: ");Serial.println(jsonCode);
return jsonCode;
}
/*
//建立json信息v5
String buildJson(int type){
Serial.println("開始建立Json信息");
// 開始ArduinoJson Assistant的serialize代碼
const size_t capacity = JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(3)+140;
DynamicJsonDocument doc(capacity);
if (type == 1){
JsonObject info = doc.createNestedObject("info");
info["name"] = "taichimaker";
info["url"] = "www.taichi-maker.com";
info["email"] = "taichimaker@163.com";
}
if (type == 2){
JsonObject digital_pin = doc.createNestedObject("digital_pin");
digital_pin["d1"] = String(digitalRead(D1));
digital_pin["d2"] = String(digitalRead(D2));
digital_pin["d3"] = String(digitalRead(D3));
}
if (type == 3){
JsonObject analog_pin = doc.createNestedObject("analog_pin");
analog_pin["a0"] = String(analogRead(A0));
}
// 結(jié)束assistant的serialize代碼
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("type=");
Serial.println(type);
Serial.print("json Code: ");Serial.println(jsonCode);
return jsonCode;
}
*/
六、MQTT的connect與publish在各情景下的區(qū)別
訂閱主題-基礎(chǔ)
void connectMQTTServer(){
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
String clientId = "esp8266-" + WiFi.macAddress();
// 連接MQTT服務(wù)器
if (mqttClient.connect(clientId.c_str())) {
Serial.println("MQTT Server Connected.");
Serial.println("Server Address: ");
Serial.println(mqttServer);
Serial.println("ClientId:");
Serial.println(clientId);
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(3000);
}
}
訂閱主題-Qos
const int subQoS = 1; // 客戶端訂閱主題時使用的QoS級別(截止2020-10-07,僅支持QoS = 1,不支持QoS = 2)
const char* willTopic = "willTopic"; // 遺囑主題名稱
const int willQos = 0; // 遺囑QoS
const int willRetain = false; // 遺囑保留
const char* willMsg = "willMsg"; // 遺囑主題信息
const bool cleanSession = false; // 清除會話(如QoS>0必須要設(shè)為false)
// 連接MQTT服務(wù)器并訂閱信息
void connectMQTTserver(){
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
String clientId = "client-" + WiFi.macAddress();
/* 連接MQTT服務(wù)器
boolean connect(const char* id, const char* user,
const char* pass, const char* willTopic,
uint8_t willQos, boolean willRetain,
const char* willMessage, boolean cleanSession);
若讓設(shè)備在離線時仍然能夠讓qos1工作,則connect時的cleanSession需要設(shè)置為false
*/
if (mqttClient.connect(clientId.c_str(), NULL, NULL, willTopic, willQos, willRetain, willMsg, cleanSession)) {
Serial.print("MQTT Server Connected. ClientId: ");
Serial.println(clientId);
subscribeTopic(); // 訂閱指定主題
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(5000);
}
}
// 訂閱指定主題
void subscribeTopic(){
String topicString = "Qos-test";
char subTopic[topicString.length() + 1];
strcpy(subTopic, topicString.c_str());
// 通過串口監(jiān)視器輸出是否成功訂閱主題以及訂閱的主題名稱
// 請注意subscribe函數(shù)第二個參數(shù)數(shù)字為QoS級別。這里為QoS = 1
if(mqttClient.subscribe(subTopic, subQoS)){
Serial.print("Subscribed Topic: ");
Serial.println(subTopic);
} else {
Serial.print("Subscribe Fail...");
}
}
訂閱主題-遺囑
// 遺囑設(shè)置
const char* willMsg = "CLIENT-OFFLINE"; // 遺囑消息內(nèi)容
const int willQoS = 0; // 遺囑QoS
const bool willRetain = false; // 遺囑保留
// 連接MQTT服務(wù)器并訂閱信息
void connectMQTTserver(){
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
String clientId = "esp8266-" + WiFi.macAddress();
// 建立遺囑主題。主題名稱以Taichi-Maker-為前綴,后面添加設(shè)備的MAC地址,最后
// 以“-Will”結(jié)尾,這是為確保不同ESP8266客戶端的遺囑主題名稱各不相同。
String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";
char willTopic[willString.length() + 1];
strcpy(willTopic, willString.c_str());
// 連接MQTT服務(wù)器,在連接過程中提供以下參數(shù):
// 客戶端ID,遺囑主題,遺囑QoS,遺囑保留,遺囑信息
if (mqttClient.connect(clientId.c_str(), willTopic, willQoS, willRetain, willMsg)){
Serial.println("MQTT Server Connected.");
Serial.print("Server Address: ");Serial.println(mqttServer);
Serial.print("ClientId: ");Serial.println(clientId);
Serial.print("Will Topic: ");Serial.println(willTopic);
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(5000);
}
}
訂閱主題-用戶密碼認證
// MQTT服務(wù)端連接用戶名密碼
const char* mqttUserName = "test-user";
const char* mqttPassword = "ranye-iot";
void connectMQTTServer(){
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
String clientId = "esp8266-" + WiFi.macAddress();
// 連接MQTT服務(wù)器。此處使用了程序首部定義的用戶名和密碼來實現(xiàn)MQTT服務(wù)端認證
if (mqttClient.connect(clientId.c_str(), mqttUserName, mqttPassword)) {
Serial.println("MQTT Server Connected.");
Serial.print("Server Address: ");
Serial.println(mqttServer);
Serial.print("ClientId: ");
Serial.println(clientId);
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(3000);
}
}
// 發(fā)布信息
void pubMQTTmsg(){
static int value;
// 建立發(fā)布主題。使用然也物聯(lián)免費端口時,主題名稱必須以test-user/為前綴。
String topicString = "test-user/" + WiFi.macAddress();
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
// 建立發(fā)布信息。信息內(nèi)容以Hello World為起始,后面添加發(fā)布次數(shù)。
String messageString = "Hello World " + String(value++);
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 實現(xiàn)ESP8266向主題發(fā)布信息
if(mqttClient.publish(publishTopic, publishMsg)){
Serial.println("Publish Topic:");Serial.println(publishTopic);
Serial.println("Publish message:");Serial.println(publishMsg);
} else {
Serial.println("Message Publish Failed.");
}
}
發(fā)布消息
void pubMQTTmsg(){
static int value; // 客戶端發(fā)布信息用數(shù)字
// 建立發(fā)布主題。主題名稱以Taichi-Maker-為前綴,后面添加設(shè)備的MAC地址。
// 這么做是為確保不同用戶進行MQTT信息發(fā)布時,ESP8266客戶端名稱各不相同,
String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress();
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
// 建立發(fā)布信息。信息內(nèi)容以Hello World為起始,后面添加發(fā)布次數(shù)。
String messageString = "Hello World " + String(value++);
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 實現(xiàn)ESP8266向主題發(fā)布信息
if(mqttClient.publish(publishTopic, publishMsg)){
Serial.println("Publish Topic:");Serial.println(publishTopic);
Serial.println("Publish message:");Serial.println(publishMsg);
} else {
Serial.println("Message Publish Failed.");
}
}
收到信息后的回調(diào)函數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-861474.html
// 收到信息后的回調(diào)函數(shù)
void receiveCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println("");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
if ((char)payload[0] == '1') { // 如果收到的信息以“1”為開始
digitalWrite(LED_BUILTIN, LOW); // 則點亮LED。
} else {
digitalWrite(LED_BUILTIN, HIGH); // 否則熄滅LED。
}
}
MQTT匯總文章來源地址http://www.zghlxwxcb.cn/news/detail-861474.html
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// 設(shè)置wifi接入信息(請根據(jù)您的WiFi信息進行修改)
const char* ssid = "RFID";
const char* password = "12345678";
const char* mqttServer = "test.ranye-iot.net";
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
const int subQoS = 1; // 客戶端訂閱主題時使用的QoS級別(截止2020-10-07,僅支持QoS = 1,不支持QoS = 2)
const bool cleanSession = false; // 清除會話(如QoS>0必須要設(shè)為false)
const char* willTopic = "willTopic"; // 遺囑主題名稱
const char* willMsg = "willMsg"; // 遺囑主題信息
const int willQos = 0; // 遺囑QoS
const int willRetain = false; // 遺囑保留
const char* mqttUserName = "test-user"; // 服務(wù)端連接用戶名
const char* mqttPassword = "ranye-iot"; // 服務(wù)端連接密碼
//然也物聯(lián)免費端口只提供這一個用戶名密碼
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // 設(shè)置板上LED引腳為輸出模式
digitalWrite(LED_BUILTIN, HIGH); // 啟動后關(guān)閉板上LED
Serial.begin(9600); // 啟動串口通訊
//設(shè)置ESP8266工作模式為無線終端模式
WiFi.mode(WIFI_STA);
// 連接WiFi
connectWifi();
// 設(shè)置MQTT服務(wù)器和端口號
mqttClient.setServer(mqttServer, 1883);
mqttClient.setCallback(receiveCallback);
// 連接MQTT服務(wù)器
connectMQTTserver();
}
void loop() {
// 如果開發(fā)板未能成功連接服務(wù)器,則嘗試連接服務(wù)器
if (!mqttClient.connected()) {
connectMQTTserver();
}
// 處理信息以及心跳
mqttClient.loop();
}
// 連接MQTT服務(wù)器并訂閱信息
void connectMQTTserver(){
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
String clientId = "client-" + WiFi.macAddress();
/* 連接MQTT服務(wù)器
boolean connect(const char* id, const char* user,
const char* pass, const char* willTopic,
uint8_t willQos, boolean willRetain,
const char* willMessage, boolean cleanSession);
若讓設(shè)備在離線時仍然能夠讓qos1工作,則connect時的cleanSession需要設(shè)置為false
*/
if (mqttClient.connect(clientId.c_str(), mqttUserName,
mqttPassword, willTopic,
willQos, willRetain, willMsg, cleanSession)) {
Serial.print("MQTT Server Connected. ClientId: ");
Serial.println(clientId);
Serial.print("MQTT Server: ");
Serial.println(mqttServer);
subscribeTopic(); // 訂閱指定主題
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(5000);
}
}
// 收到信息后的回調(diào)函數(shù)
void receiveCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println("");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
if ((char)payload[0] == '1') { // 如果收到的信息以“1”為開始
digitalWrite(BUILTIN_LED, LOW); // 則點亮LED。
} else {
digitalWrite(BUILTIN_LED, HIGH); // 否則熄滅LED。
}
}
// 訂閱指定主題
void subscribeTopic(){
// 建立訂閱主題。使用然也物聯(lián)的免費端口進行用戶名密碼連接時只能以"test-user/"開頭
// 這么做是為確保不同設(shè)備使用同一個MQTT服務(wù)器測試消息訂閱時,所訂閱的主題名稱不同
String topicString = "test-user/" + WiFi.macAddress();
char subTopic[topicString.length() + 1];
strcpy(subTopic, topicString.c_str());
// 通過串口監(jiān)視器輸出是否成功訂閱主題以及訂閱的主題名稱
// 請注意subscribe函數(shù)第二個參數(shù)數(shù)字為QoS級別。這里為QoS = 1
if(mqttClient.subscribe(subTopic, subQoS)){
Serial.print("Subscribed Topic: ");
Serial.println(subTopic);
} else {
Serial.print("Subscribe Fail...");
}
}
// ESP8266連接wifi
void connectWifi(){
WiFi.begin(ssid, password);
//等待WiFi連接,成功連接后輸出成功信息
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected!");
Serial.println("");
}
到了這里,關(guān)于【ESP8266教程】零基礎(chǔ)入門學用物聯(lián)網(wǎng)-基礎(chǔ)知識篇(太極創(chuàng)客團隊)學習筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!