国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【ESP8266教程】零基礎(chǔ)入門學用物聯(lián)網(wǎng)-基礎(chǔ)知識篇(太極創(chuàng)客團隊)學習筆記

這篇具有很好參考價值的文章主要介紹了【ESP8266教程】零基礎(chǔ)入門學用物聯(lián)網(wǎng)-基礎(chǔ)知識篇(太極創(chuàng)客團隊)學習筆記。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

提示:這里可以添加本文要記錄的大概內(nèi)容:

例如:隨著人工智能的不斷發(fā)展,機器學習這門技術(shù)也越來越重要,很多人都開啟了學習機器學習,本文就介紹了機器學習的基礎(chǔ)內(nèi)容。


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、ESP8266開發(fā)板詳解

1.引腳圖

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

????????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é)議族

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

????????1.鏈路層的主要作用是實現(xiàn)設(shè)備之間的物理鏈接,如WiFi

????????2.網(wǎng)絡(luò)層為網(wǎng)絡(luò)設(shè)備提供地址——IP協(xié)議

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機????????

????????IP協(xié)議分為IPV4和IPV6,IPV4由4個十進制數(shù)(0~255)組成

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

? ? ? ? 默認網(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)

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

? ? ? ? 而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)

????????請求

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

????????響應(yīng)

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

2.ESP8266工作模式

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

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中讀取

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

? ? ? ? 若程序使用了Flash,需配置一下Flash Size

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

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文件夾中

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

????????根據(jù)所要上傳的文件大小調(diào)整Flash Size大小?

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

六、使用閃存文件系統(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)

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

注意書寫格式,如GET / HTTP中間的空格?

?在http請求時,我們一般會在request header 或 response header 中看到”Connection:Keep-Alive”或 “Connection:close”,這里具體的含義是有關(guān)http 請求的是否保持長連接,即鏈接是否復(fù)用,每次請求是復(fù)用已建立好的請求,還是重新建立一個新的請求。

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

響應(yīng)體即www.example.com的網(wǎng)頁信息

2.

客戶端向服務(wù)器發(fā)送數(shù)據(jù)信息

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

GET即可以用來發(fā)送信息也可以用來請求信息?

3.

客戶端向服務(wù)器請求數(shù)據(jù)信息

七、JSON

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

size_t? 相當于? unsigned long

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

?esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

?效果如下esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

?esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

這樣也打印的是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;
}

使用官方工具建立步驟

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

?首先復(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ū)別

esp8266引腳圖及其功能,物聯(lián)網(wǎng),學習,單片機

訂閱主題-基礎(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ù)

// 收到信息后的回調(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)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C#,入門教程(20)——列表(List)的基礎(chǔ)知識

    C#,入門教程(20)——列表(List)的基礎(chǔ)知識

    上一篇: C#,入門教程(19)——循環(huán)語句(for,while,foreach)的基礎(chǔ)知識 https://blog.csdn.net/beijinghorn/article/details/124060844 List顧名思義就是數(shù)據(jù)列表,區(qū)別于數(shù)據(jù)數(shù)組(array)。 List比數(shù)組提供強大得多!多!多!多!的功能,能存儲更多!多!多!類型的數(shù)據(jù)(泛型)! List是更

    2024年01月16日
    瀏覽(89)
  • C#,入門教程(15)——類(class)的基礎(chǔ)知識

    C#,入門教程(15)——類(class)的基礎(chǔ)知識

    上一篇: C#,入門教程(14)——字符串與其他數(shù)據(jù)類型的轉(zhuǎn)換 https://blog.csdn.net/beijinghorn/article/details/124004562 物以類聚,凡物必類。 類的使用,須遵循幾個簡單的原則: (1)能類則類,留有余地。 (2)凡數(shù)據(jù)體及其集合,必寫為類; (3)凡類,必獨立文件; 類class實際上可

    2024年01月20日
    瀏覽(24)
  • C#,入門教程(24)——類索引器(this)的基礎(chǔ)知識

    C#,入門教程(24)——類索引器(this)的基礎(chǔ)知識

    上一篇: ? C#,入門教程(23)——數(shù)據(jù)類型轉(zhuǎn)換的一點基礎(chǔ)知識 https://blog.csdn.net/beijinghorn/article/details/124187182 工業(yè)軟件首先要求高可靠性、高可維護性。 作為工業(yè)軟件的開發(fā)者,我們對語言重載的需求是:“ 不可或缺 ”。 沒有重載幾乎就無法開展大規(guī)模的工業(yè)軟件編程項目

    2024年01月22日
    瀏覽(23)
  • 【流光溢彩】物聯(lián)網(wǎng)入門 - ESP8266 + WS2812B 制作流光溢彩燈帶

    【流光溢彩】物聯(lián)網(wǎng)入門 - ESP8266 + WS2812B 制作流光溢彩燈帶

    ESP8266 模塊 x1 WS2812B 燈帶(60/米,根據(jù)顯示器四周長度買即可) x1 杜邦線 若干 DC 電源 x1 1. ESP8266 串口驅(qū)動 一般購買詳情頁都會有寫,沒有就找商家要一個。 一般是 CH340 或者 CP2102,我買的是 CP2102 2. WLED 固件 固件開源地址:https://github.com/Aircoookie/WLED/releases 下載 ESP8266.bin 結(jié)

    2024年02月09日
    瀏覽(21)
  • LaTeX詳細安裝教程|LaTeX 基礎(chǔ)知識|LaTeX 常用語法|LaTeX 快速入門

    LaTeX詳細安裝教程|LaTeX 基礎(chǔ)知識|LaTeX 常用語法|LaTeX 快速入門

    LaTeX 是一種專業(yè)的排版系統(tǒng),主要用于科技文獻、學術(shù)論文、書籍等的排版。與傳統(tǒng)的文字處理軟件相比,LaTeX 可以更好地管理大型文字項目,并提供了豐富的數(shù)學公式和符號支持。本篇博客將介紹 LaTeX 的基礎(chǔ)知識、常用語法以及安裝教程。 LaTeX 具有如下特點: 專業(yè)的排版

    2024年02月05日
    瀏覽(28)
  • ESP8266入門教程12:自動配網(wǎng)

    ESP8266入門教程12:自動配網(wǎng)

    下載第三方庫WiFiManager到lib文件夾 ??git clone https://github.com/tzapu/WiFiManager.git 第2行:包含WiFiManager庫的頭文件 第12行:創(chuàng)建WiFiManager對象 第14行:配置自動配網(wǎng)熱點名稱 1、編譯并上傳固件,然后使用手機連接名稱叫做“ESP8266-Auto”的WIFI熱點 2、點擊【Configure WiFi】開始配網(wǎng),

    2024年02月12日
    瀏覽(37)
  • C#,入門教程(28)——文件夾(目錄)、文件讀(Read)與寫(Write)的基礎(chǔ)知識

    C#,入門教程(28)——文件夾(目錄)、文件讀(Read)與寫(Write)的基礎(chǔ)知識

    上一篇: ? C#,入門教程(27)——應(yīng)用程序(Application)的基礎(chǔ)知識 https://blog.csdn.net/beijinghorn/article/details/125094837 C#知識比你的預(yù)期簡單的多,但也遠遠超乎你的想象! 與 文件 相關(guān)的知識,不算多。 作為初學者,先學習 文本文件 的讀寫,就足夠應(yīng)付好幾年了。 文件 自然是

    2024年01月23日
    瀏覽(20)
  • STC8H系列單片機入門教程之ADC基礎(chǔ)知識(四)

    STC8H系列單片機入門教程之ADC基礎(chǔ)知識(四)

    目錄 一、A/D轉(zhuǎn)換過程 二、ADC轉(zhuǎn)換流程圖 三、采樣定理 四、ADC基本參數(shù) 4.1、分辨率 4.2、采樣速率 4.3、轉(zhuǎn)換時間 4.4、量程? 4.5、最低有效位 五、靜態(tài)參數(shù) 5.1、微分非線性 5.2、積分非線性 六、逐次逼近型模數(shù)轉(zhuǎn)換器 七、ADC常用分壓電路 八、示例代碼 ADC即模數(shù)轉(zhuǎn)換器,用來

    2024年04月11日
    瀏覽(23)
  • ESP8266入門教程03:點亮LED燈

    ESP8266入門教程03:點亮LED燈

    ESP8266默認是高電平工作,所以想要點亮LED只需要給相應(yīng)的引腳設(shè)置低電平即可。 ?第11行:使用pinMode(pin, mode)來設(shè)置GPIO口工作模式,pin取值范圍0 ~ 16,數(shù)字引腳0-15可設(shè)置為INPUT、OUTPUT、INPUT_PULLUP模式(輸入、輸出、上拉輸入);數(shù)字引腳16可設(shè)置為INPUT、OUTPUT、INPUT_PULLDOWN_16模式

    2024年02月14日
    瀏覽(103)
  • Python入門教程:掌握for循環(huán)、while循環(huán)、字符串操作、文件讀寫與異常處理等基礎(chǔ)知識

    Python入門教程:掌握for循環(huán)、while循環(huán)、字符串操作、文件讀寫與異常處理等基礎(chǔ)知識

    在 Python 中,for 循環(huán)用于遍歷序列(list、tuple、range 對象等)或其他可迭代對象。for 循環(huán)的基本語法如下: 其中, 變量 表示每次循環(huán)中取出的一個元素, 可迭代對象 表示被遍歷的對象。下面是一個 for 循環(huán)的例子: 輸出結(jié)果為: 代碼中, fruits 是一個列表, fruit 是當前循

    2024年02月10日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包