前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ESP8266开发板详解

1.引脚图

NodeMCU上的D2引脚引出ESP8266芯片的GPIO4引脚

即digitalWrite(D2,HIGH);等价于digitalWrite(4,HIGH);

D开头的是数字引脚,A开头的是模拟引脚(右下角的ADC引脚)

3V3可以为外界提供3.3V电压,Vin为NodeMCU供电(也可以用数据线供电)

数字引脚为3.3V,digitalWrite(D2,HIGH);即是将D2引脚置为3.3V.而digitalRead(D2);

引脚所连电压不能超过3.3V。

模拟引脚可读电压范围为0-1V。

USB下载串口占用的是RX和TX(GPIO3和GPIO1)

蓝底黑字都是通讯端口(如GPIO3、GPIO1等)

黑底白字都是NodeMCU操作内部存储单元的引脚(如GPIO6、GPIO15等)

注意:GPIO6-GPIO11不要使用

二、互联网基础

1.TCP/IP协议族

1.链路层的主要作用是实现设备之间的物理链接,如WiFi

2.网络层为网络设备提供地址——IP协议

IP协议分为IPV4和IPV6,IPV4由4个十进制数(0~255)组成

默认网关即WiFi路由器的IP地址

子网掩码用来区分IP地址的子网地址与机器本身地址

参考:互联网知识基础-网络层(第2章 – 第3节) – 太极创客 (taichi-maker.com)

而IPV6由8组16进制数组成,可以为更多网络设备提供独立的IP地址

3.传输层——TCP协议

TCP协议特点:稳

·可保证所有数据都能被接收端接收

·数据的传输顺序不会被打乱

·传输数据如有损坏则重发受损数据

适用于电子邮件、文件传输等领域

传输层——UDP协议

UDP协议特点:快

·UDP比TCP速度快

·不保证所有数据都能被接收端接收

·数据一旦受损,UDP协议将抛弃受损数据

·传输数据如有损坏不会重发受损数据

适用于在线语音/视频、网游等领域

4.应用层

最常用HTTP协议,HTTP协议由请求和响应组成,类似于一问一答,具体参考:互联网知识基础-应用层(第2章 – 第5节) – 太极创客 (taichi-maker.com)

请求

响应

2.ESP8266工作模式

1.AP(Access Point)模式(接入点模式)类似于手机热点

2.无线终端模式(Wireless Station)

3.混合模式

三、ESP8266接入点模式及无线终端模式

1.接入点模式代码

3-1-3 NodeMCU开发板的接入点模式 – 太极创客 (taichi-maker.com)

/*
NodeMCU接入点模式
By 太极创客(http://www.taichi-maker.com)
2019-03-11此程序用于演示如何将NodeMCU以接入点模式工作。通过此程序,您可以使用
电脑或者手机连接NodeMCU所建立WiFi网络。网络名: taichi-maker
密码:12345678如需获得更多关于如何使用NodeMCU开发物联网的教程和资料信息
请参考太极创客网站(http://www.taichi-maker.com)
并在首页搜索栏中搜索关键字:物联网
*/#include <ESP8266WiFi.h>        // 本程序使用ESP8266WiFi库const char *ssid = "taichi-maker"; // 这里定义将要建立的WiFi名称。此处以"taichi-maker"为示例// 您可以将自己想要建立的WiFi名称填写入此处的双引号中const char *password = "12345678";  // 这里定义将要建立的WiFi密码。此处以12345678为示例// 您可以将自己想要使用的WiFi密码放入引号内// 如果建立的WiFi不要密码,则在双引号内不要填入任何信息void setup() {Serial.begin(9600);              // 启动串口通讯WiFi.softAP(ssid, password);     // 此语句是重点。WiFi.softAP用于启动NodeMCU的AP模式。// 括号中有两个参数,ssid是WiFi名。password是WiFi密码。// 这两个参数具体内容在setup函数之前的位置进行定义。Serial.print("Access Point: ");    // 通过串口监视器输出信息Serial.println(ssid);              // 告知用户NodeMCU所建立的WiFi名Serial.print("IP address: ");      // 以及NodeMCU的IP地址Serial.println(WiFi.softAPIP());   // 通过调用WiFi.softAPIP()可以得到NodeMCU的IP地址
}void loop() {
}

2.无线终端模式代码

3-1-4 NodeMCU开发板的无线终端模式 – 太极创客 (taichi-maker.com)

/*
NodeMCU无线终端模式连接WiFi
By 太极创客(http://www.taichi-maker.com)
2019-03-11本示例程序用于演示如何使用NodeMCU无线终端模式连接WiFi如需获得更多关于如何使用NodeMCU开发物联网的教程和资料信息
请参考太极创客网站(http://www.taichi-maker.com)
并在首页搜索栏中搜索关键字:物联网
*/#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);                  // 启动网络连接Serial.print("Connecting to ");              // 串口监视器输出网络连接信息Serial.print(ssid); Serial.println(" ...");  // 告知用户NodeMCU正在尝试WiFi连接int i = 0;                                   // 这一段程序语句用于检查WiFi是否连接成功while (WiFi.status() != WL_CONNECTED) {      // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。 delay(1000);                               // 如果WiFi连接成功则返回值为WL_CONNECTED                       Serial.print(i++); Serial.print(' ');      // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值}                                            // 同时NodeMCU将通过串口监视器输出连接时长读秒。// 这个读秒是通过变量i每隔一秒自加1来实现的。Serial.println("");                          // WiFi连接成功后Serial.println("Connection established!");   // NodeMCU将通过串口监视器输出"连接成功"信息。Serial.print("IP address:    ");             // 同时还将输出NodeMCU的IP地址。这一功能是通过调用Serial.println(WiFi.localIP());              // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
}void loop() {
}

四、 建立基本网络服务器

1.建立基本网络服务器

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : 3_2_1_First_Web_Server
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20191107
程序目的/Purpose          : 使用NodeMCU建立基本服务器。用户可通过浏览器使用8266的IP地址访问8266所建立的基本网页(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// 括号中的数字是网路服务器响应http请求的端口号// 网络服务器标准http端口号为80,因此这里使用80为端口号void setup(void){Serial.begin(9600);          // 启动串口通讯//通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("RFID", "rfid&iot0243"); wifiMulti.addAP("taichi-maker", "12345678");  // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。wifiMulti.addAP("taichi-maker2", "87654321"); // 这3个WiFi网络名称分别是taichi-maker, taichi-maker2, taichi-maker3。wifiMulti.addAP("taichi-maker3", "13572468"); // 这3个网络的密码分别是123456789,87654321,13572468。// 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。// 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。int i = 0;                                 while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCUSerial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。}                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是// 此处while循环判断是否跳出循环的条件。// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println('\n');                     // WiFi连接成功后Serial.print("Connected to ");            // NodeMCU将通过串口监视器输出。Serial.println(WiFi.SSID());              // 连接的WiFI名称Serial.print("IP address:\t");            // 以及Serial.println(WiFi.localIP());           // NodeMCU的IP地址//--------"启动网络服务功能"程序部分开始-------- //  此部分为程序为本示例程序重点1esp8266_server.begin();                   //  详细讲解请参见太极创客网站《零基础入门学用物联网》esp8266_server.on("/", handleRoot);       //  第3章-第2节 ESP8266-NodeMCU网络服务器-1esp8266_server.onNotFound(handleNotFound);
//--------"启动网络服务功能"程序部分结束--------Serial.println("HTTP esp8266_server started");//  告知用户ESP8266网络服务功能已经启动
}/* 以下函数语句为本示例程序重点3
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节 3_2_1_First_Web_Server 的说明讲解*/
void loop(void){esp8266_server.handleClient();     // 处理http服务器访问(检查是否有浏览器请求网页信息)
}/* 以下两个函数为本示例程序重点2
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节 3_2_1_First_Web_Server 的说明讲解*/
void handleRoot() {   //处理网站根目录“/”的访问请求 esp8266_server.send(200, "text/plain", "臭婆娘~ o(* ̄▽ ̄*)o这招你会不会捏");   // NodeMCU将调用此函数。
}// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){                                        // 当浏览器请求的网络资源无法在服务器找到时,esp8266_server.send(404, "text/plain", "404: Not found");   // NodeMCU将调用此函数。
}

2.通过网络服务实现NodeMCU开发板基本控制

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : 3_2_2_Turning_on_and_off_an_LED
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20191108
程序目的/Purpose          : 使用NodeMCU建立基本服务器。用户可通过浏览器使用8266的IP地址访问8266所建立的基本网页并通过该页面点亮/熄灭NodeMCU的内置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);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)void setup(void){Serial.begin(9600);   // 启动串口通讯pinMode(LED_BUILTIN, OUTPUT); //设置内置LED引脚为输出模式以便控制LEDwifiMulti.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再启动后会扫描当前网络wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 环境查找是否有这里列出的WiFi ID。如果有Serial.println("Connecting ...");                            // 则尝试使用此处存储的密码进行连接。int i = 0;                                 while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCUSerial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。}                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是// 此处while循环判断是否跳出循环的条件。// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println('\n');Serial.print("Connected to ");Serial.println(WiFi.SSID());              // 通过串口监视器输出连接的WiFi名称Serial.print("IP address:\t");Serial.println(WiFi.localIP());           // 通过串口监视器输出ESP8266-NodeMCU的IPesp8266_server.begin();                           // 启动网站服务esp8266_server.on("/", HTTP_GET, handleRoot);     // 设置服务器根目录即'/'的函数'handleRoot'/*当有浏览器请求首页"/"并且方法是HTTP_GET时,才调用handleRoot*/esp8266_server.on("/LED", HTTP_POST, handleLED);  // 设置处理LED控制请求的函数'handleLED'/*当有浏览器请求页面"/LED"并且方法是HTTP_POST时,才调用handleLED*/esp8266_server.onNotFound(handleNotFound);        // 设置处理404情况的函数'handleNotFound'Serial.println("HTTP esp8266_server started");//  告知用户ESP8266网络服务功能已经启动
}void loop(void){esp8266_server.handleClient();                     // 检查http服务器访问
}/*设置服务器根目录即'/'的函数'handleRoot'该函数的作用是每当有客户端访问NodeMCU服务器根目录时,NodeMCU都会向访问设备发送 HTTP 状态 200 (Ok) 这是send函数的第一个参数。同时NodeMCU还会向浏览器发送HTML代码,以下示例中send函数中第三个参数,也就是双引号中的内容就是NodeMCU发送的HTML代码。该代码可在网页中产生LED控制按钮。 当用户按下按钮时,浏览器将会向NodeMCU的/LED页面发送HTTP请求,请求方式为POST。NodeMCU接收到此请求后将会执行handleLED函数内容*/
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方式跳转到/LED页面
*///处理LED控制请求的函数'handleLED'
void handleLED() {                          digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// 改变LED的点亮或者熄灭状态,翻转IO口esp8266_server.sendHeader("Location","/");          // 跳转回页面根目录(首页)esp8266_server.send(303);                           // 发送Http相应代码303 跳转
}// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){esp8266_server.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

3.通过网络服务将开发板引脚状态显示在网页中

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : 3_2_4_Pin_State_Display_Auto_Refresh
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200128
程序目的/Purpose          : 使用NodeMCU建立基本服务器。该网页将显示引脚D3状态。同时状态会每隔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)因为它已经与开发板上的FLASH按键开关连接好了。ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)bool pinState;                      // 存储引脚状态用变量void setup(){Serial.begin(9600);          // 启动串口通讯delay(10);Serial.println("");pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式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在启动后会扫描当前网络wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 环境查找是否有这里列出的WiFi ID。如果有Serial.println("Connecting ...");                            // 则尝试使用此处存储的密码进行连接。// 另外这里只存储了3个WiFi信息,您可以存储更多// 的WiFi信息在此处。int i = 0;                                 while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCUSerial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。}                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是// 此处while循环判断是否跳出循环的条件。// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println('\n');                     // WiFi连接成功后Serial.print("Connected to ");            // NodeMCU将通过串口监视器输出。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网络服务功能已经启动
}void loop(){esp8266_server.handleClient();     // 处理http服务器访问pinState = digitalRead(buttonPin); // 获取引脚状态
}                                                                   /* 以下函数处理网站首页的访问请求。此函数为本示例程序重点1
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节“通过网络服务将开发板引脚状态显示在网页中”的说明讲解。*/
void handleRoot() {   //处理网站目录“/”的访问请求 esp8266_server.send(200, "text/html", sendHTML(pinState));
}/*
建立用于发送给客户端浏览器的HTML代码。此代码将会每隔5秒刷新页面。
通过页面刷新,引脚的最新状态也会显示于页面中
*/
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;
}// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){                                        // 当浏览器请求的网络资源无法在服务器找到时,esp8266_server.send(404, "text/plain", "404: Not found");   // NodeMCU将调用此函数。
}

五、ESP8266闪存文件系统

ESP8266闪存文件系统基本操作

1.ESP8266闪存文件系统大小

大小一般为4MB,具体以生产商为准,可以从Arduino IDE中读取

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

2.通过程序向闪存文件系统写入信息

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-write
团队/Team                 : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author               : CYNO 朔
日期/Date(YYYYMMDD)      : 20191109
程序目的/Purpose           : 此程序用于演示如何向NodeMCU的SPIFFS中建立名为notes.txt的文件,程序还将向该文件写入信息。
-----------------------------------------------------------------------
函数说明:
SPIFFS.open(file_name, "w");
以上函数有两个参数:
第一个参数是被操作的文件名称,本示例中该文件为/notes.txt
第二个参数"w" 代表写入文件信息。(如需了解如何读取信息,请参阅示例程序esp8266-flash-read)
***********************************************************************/#include <FS.h>//包含闪存的一些函数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)闪存文件系统Serial.println("SPIFFS format finish");if(SPIFFS.begin()){ // 启动SPIFFSSerial.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();                           // 完成文件写入后关闭文件Serial.println("Finished Writing data to SPIFFS");
}void loop() {
}

3. 通过程序从闪存文件系统读取信息

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-read
团队/Team                 : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author               : CYNO 朔
日期/Date(YYYYMMDD)      : 20191109
程序目的/Purpose           : 此程序用于演示如何从NodeMCU的内置SPIFFS中存储的文件notes.txt读取数据。notes.txt 文件内容将会通过串口监视器显示出来供用户确认。注意在使用本程序以前需要先将notes.txt 文件上传到NodeMCU开发板的SPIFFS中
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
-----------------------------------------------------------------------
函数说明:
SPIFFS.open(file_name, "r");
以上SPIFFS函数有两个参数:
第一个参数是被操作的文件名称,本示例中该文件为/notes.txt
第二个参数"r" 代表读取文件信息。(如需了解如何写入信息,请参阅示例程序esp8266-flash-write)
***********************************************************************/#include <FS.h>String file_name = "/taichi-maker/notes.txt";              //被读取的文件位置和名称void setup() {Serial.begin(9600);Serial.println("");if(SPIFFS.begin()){ // 启动闪存文件系统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");//读取文件内容并且通过串口监视器输出文件信息for(int i=0; i<dataFile.size(); i++){Serial.print((char)dataFile.read());       }//完成文件读取后关闭文件dataFile.close();
}void loop() {
}

4. 通过程序向闪存文件系统文件添加信息

使用"a"会从文件尾部开始写,而"w"操作将会在文件系统中建立该文件。如果文件系统有该文件,则程序将会重新建立该文件,即原有文件信息将会被覆盖。

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-append
团队/Team                 : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author               : CYNO 朔
日期/Date(YYYYMMDD)      : 20191109
程序目的/Purpose           : 此程序用于演示如何向NodeMCU的内置SPIFFS中存储的文件notes.txt添加数据。
-----------------------------------------------------------------------
函数说明:
SPIFFS.open(file_name, "a");
以上SPIFFS函数有两个参数:
第一个参数是被操作的文件名称,本示例中该文件为/notes.txt
第二个参数"a" 代表添加文件信息。(如需了解如何读取信息,请参阅示例程序esp8266-flash-read)
此示例程序所演示的是向SPIFFS中的文件里添加信息。这一操作写入信息有所区别。
添加信息是不会删除文件内原有信息,而是在原有信息后面添加新的信息。
但写入操作(示例 esp8266-flash-write.ino)是将文件内容完全清除,重新写入新信息。
***********************************************************************/#include <FS.h>String file_name = "/taichi-maker/notes.txt";              //被读取的文件位置和名称void setup() {Serial.begin(9600);Serial.println("");if(SPIFFS.begin()){ // 启动闪存文件系统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"即AppenddataFile.println("This is Appended Info."); // 向dataFile添加字符串信息dataFile.close();                           // 完成文件操作后关闭文件   Serial.println("Finished Appending data to SPIFFS");} else {Serial.print(file_name);Serial.print(" NOT FOUND.");}}void loop() {
}

5. 通过程序读取目录内容(读取文件夹中所包含文件)

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-folder-read
团队/Team                 : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author               : CYNO 朔
日期/Date(YYYYMMDD)      : 20191109
程序目的/Purpose           : 此程序用于演示如何从NodeMCU的内置SPIFFS中文件夹里读取文件信息文件夹内容将会通过串口监视器显示出来。-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
-----------------------------------------------------------------------
函数说明:
SPIFFS.openDir(folder_name);
以上函数打开指定目录并返回一个目录对象实例。
***********************************************************************/#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()){ // 启动闪存文件系统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();                           // 完成文件写入后关闭文件Serial.println(F("Finished Writing data to SPIFFS"));/*添加 F() 相当于为字符串常量定义了PROGMEM属性,常量字符串仍然存储在FLASH中,但是程序运行时不会再将常量字符串从FLASH中copy到SRAM中,而是直接读取FLASH中的字符串,这样一来就节约了SRAM,但是代码运行速度就下降了。*/// 显示目录中文件内容以及文件大小Dir dir = SPIFFS.openDir(folder_name);  // 建立“目录”对象 dir=folder_name="/taichi-maker"while (dir.next()) {  // dir.next()用于检查目录中是否还有“下一个文件”Serial.println(dir.fileName()); // 输出文件名}
}void loop() {
}

6. 从闪存文件系统中删除文件

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-remove
团队/Team                 : 太极创客团队 / 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()){ // 启动闪存文件系统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. 显示闪存文件系统信息

/**********************************************************************
项目名称/Project           : 零基础入门学用物联网
程序名称/Program name      : esp8266-flash-info
团队/Team                 : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author               : CYNO 朔
日期/Date(YYYYMMDD)      : 20200204
程序目的/Purpose           : 此程序用于演示如何使用FSInfo对象来显示闪存文件系统状态
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
***********************************************************************/#include <FS.h>FSInfo fs_info;void setup() {Serial.begin(9600);SPIFFS.begin();       //启动SPIFFSSerial.println("");Serial.println("SPIFFS Started.");// 闪存文件系统信息SPIFFS.info(fs_info);// 可用空间总和(单位:字节)Serial.print("totalBytes: ");     Serial.print(fs_info.totalBytes); Serial.println(" Bytes"); // 已用空间(单位:字节)Serial.print("usedBytes: "); Serial.print(fs_info.usedBytes);Serial.println(" Bytes"); // 最大文件名字符限制(含路径和'\0')Serial.print("maxPathLength: "); Serial.println(fs_info.maxPathLength);// 最多允许打开文件数量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向闪存文件系统上传文件

将需要上传的文件保存在程序路径下的data文件夹中

根据所要上传的文件大小调整Flash Size大小

六、使用闪存文件系统建立功能更加丰富的网络服务器

  • 在网页中加载闪存文件系统中的图片、CSS和JavaScript
  • 通过网页控制ESP8266开发板的引脚
  • 通过网页文本框控制ESP8266开发板的PWM引脚
  • (Ajax)控制LED引脚并将A0引脚读数实时显示于网页中
  • (JavaScript)通过网页图形界面控制ESP8266的PWM引脚
  • (JavaScript)使用指针表显示模拟输入引脚数值
  • 通过网页将文件上传到ESP8266开发板闪存文件系统

七、ESP8266帮助文档

1.

ESP8266-Arduino库 开发参考资料 – 太极创客 (taichi-maker.com)

注意书写格式,如GET / HTTP中间的空格

在http请求时,我们一般会在request header 或 response header 中看到”Connection:Keep-Alive”或 “Connection:close”,这里具体的含义是有关http 请求的是否保持长连接,即链接是否复用,每次请求是复用已建立好的请求,还是重新建立一个新的请求。

响应体即www.example.com的网页信息

2.

客户端向服务器发送数据信息

GET即可以用来发送信息也可以用来请求信息

3.

客户端向服务器请求数据信息

七、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));// 结束assistant的serialize代码String jsonCode;  serializeJson(doc, jsonCode);Serial.print("Root Json Code: ");Serial.println(jsonCode); return jsonCode;
}

使用官方工具建立步骤

首先复制Serializing program中的代码,将1,0,1,500改为识别对应引脚的状态,capcity修改为Parsing program同样大小,这样运行更加稳定,然后修改串口打印方式

单独请求一段Json

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : cgj_server_1_serialize
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 2020517
程序目的/Purpose          :
本实例用于演示esp8266的JSON数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端。
本程序为服务器程序,功能如下:1. 实时读取A0、 D1、D2以及D3引脚的读数。
2. 当有客户端请求信息时,将会通过http响应将引脚读数等信息发送给客户端。信息发送格式为JSON格式。
3. 使用ArduinoJson库的Serialize方式建立响应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            // 按钮引脚D3ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)IPAddress local_IP(192, 168, 3, 12); // 设置ESP8266-NodeMCU联网后的IP
IPAddress gateway(192, 168, 3, 1);    // 设置网关IP(通常网关IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0);   // 设置子网掩码
IPAddress dns(192,168,3,1);           // 设置局域网DNS的IP(通常局域网DNS的IP是WiFI路由IP)void setup(){Serial.begin(9600);          // 启动串口通讯Serial.println("");// 将引脚设置为输入上拉模式pinMode(D1, INPUT_PULLUP);pinMode(D2, INPUT_PULLUP);pinMode(buttonPin, INPUT_PULLUP);   // NodeMCU开发板按键连接在D3引脚上// 设置开发板网络环境if (!WiFi.config(local_IP, gateway, subnet)) {Serial.println("Failed to Config ESP8266 IP"); } //通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("RFID", "rfid&iot0243"); // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。wifiMulti.addAP("taichi-maker2", "87654321"); // 这3个WiFi网络名称分别是taichi-maker, taichi-maker2, taichi-maker3。wifiMulti.addAP("taichi-maker3", "13572468"); // 这3个网络的密码分别是123456789,87654321,13572468。// 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。// 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。int i = 0;                                 while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCUSerial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。}                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是// 此处while循环判断是否跳出循环的条件。// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println('\n');                     // WiFi连接成功后Serial.print("Connected to ");            // NodeMCU将通过串口监视器输出。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网络服务功能已经启动
}void loop(){// 处理http服务器访问esp8266_server.handleClient();
}                                                                   void handleRoot() {   //处理网站目录“/”的访问请求 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开发板引脚信息并且建立JSON信息
// 以便ESP8266服务器通过响应信息发送给客户端
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));// 结束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客户端发送多种JSON数据信ddd息

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : client_send_multi_json
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : Dapenson
日期/Date(YYYYMMDD)     : 20200425
程序目的/Purpose          :
本实例用于演示esp8266的json数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端本程序为客户端程序,功能如下:
1. 实时读取A0、 D1、D2以及D3引脚的读数。
2. 向服务器发送多种Json信息。
3. 在有些发送的信息中包含有D3引脚状态从而控制服务器开发板上的LED点亮或熄灭
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200521      CYNO朔           001        调整以使程序与csj_client一致
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
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"; // 网络服务器地址
const int httpPort = 80;            // http端口80void setup(){Serial.begin(9600);          Serial.println("");//通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("RFID", "rfid&iot0243"); // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。wifiMulti.addAP("taichi-maker2", "87654321"); // 这3个WiFi网络名称分别是taichi-maker, taichi-maker2, taichi-maker3。wifiMulti.addAP("taichi-maker3", "13572468"); // 这3个网络的密码分别是123456789,87654321,13572468。// 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。// 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。int i = 0;                                 while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCUSerial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。}                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是// 此处while循环判断是否跳出循环的条件。// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println('\n');                     // WiFi连接成功后Serial.print("Connected to ");            // NodeMCU将通过串口监视器输出。Serial.println(WiFi.SSID());              // 连接的WiFI名称Serial.print("IP address:\t");            // 以及Serial.println(WiFi.localIP());           // NodeMCU的IP地址
}void loop(){// 发送HTTP请求,使用参数控制函数发送不同类型JSONhttpRequest(1);    delay(2000);httpRequest(2); delay(2000); httpRequest(3); delay(2000);   Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}// 向服务器发送HTTP请求,请求信息中包含json信息
void httpRequest(int jsonType){// 建立WiFi客户端对象,对象名称clientWiFiClient client;    // 根据jsonType参数建立不同类型JSONString payloadJson = buildJson(jsonType); // 建立字符串,用于HTTP请求String httpRequest =  String("GET /") + " HTTP/1.1\r\n" +"Host: " + host + "\r\n" +"Connection: close\r\n\r\n" + payloadJson;// 通过串口输出连接服务器名称以便查阅连接服务器的网址                      Serial.print("Connecting to "); Serial.print(host); if (client.connect(host, httpPort)){ Serial.println(" Success!");            // 连接成功后串口输出“Success”信息client.print(httpRequest);              // 向服务器发送请求Serial.println("Sending request: ");    // 通过串口输出HTTP请求信息内容以便查阅Serial.println(httpRequest);     Serial.println("Web Server Response:"); // 通过串口监视输出服务器响应信息        while (client.connected() || client.available()){ if (client.available()){String line = client.readStringUntil('\n');Serial.println(line);}} } else{    // 如果连接不成功则通过串口输出“连接失败”信息Serial.println(" failed!");} client.stop();                      // 断开与服务器的连接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));}// 结束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在各情景下的区别

订阅主题-基础

void connectMQTTServer(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 连接MQTT服务器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必须要设为false)// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "client-" + WiFi.macAddress();/* 连接MQTT服务器boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); 若让设备在离线时仍然能够让qos1工作,则connect时的cleanSession需要设置为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());// 通过串口监视器输出是否成功订阅主题以及订阅的主题名称// 请注意subscribe函数第二个参数数字为QoS级别。这里为QoS = 1if(mqttClient.subscribe(subTopic, subQoS)){Serial.print("Subscribed Topic: ");Serial.println(subTopic);} else {Serial.print("Subscribe Fail...");}
}

订阅主题-遗嘱

// 遗嘱设置
const char* willMsg = "CLIENT-OFFLINE"; // 遗嘱消息内容
const int willQoS = 0;                   // 遗嘱QoS
const bool willRetain = false;           // 遗嘱保留// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 连接MQTT服务器,在连接过程中提供以下参数:// 客户端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服务端连接用户名密码
const char* mqttUserName = "test-user";
const char* mqttPassword = "ranye-iot";void connectMQTTServer(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 连接MQTT服务器。此处使用了程序首部定义的用户名和密码来实现MQTT服务端认证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);}
}// 发布信息
void pubMQTTmsg(){static int value;// 建立发布主题。使用然也物联免费端口时,主题名称必须以test-user/为前缀。String topicString = "test-user/" + WiFi.macAddress();char publishTopic[topicString.length() + 1];  strcpy(publishTopic, topicString.c_str());// 建立发布信息。信息内容以Hello World为起始,后面添加发布次数。String messageString = "Hello World " + String(value++); char publishMsg[messageString.length() + 1];   strcpy(publishMsg, messageString.c_str());// 实现ESP8266向主题发布信息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."); }
}

发布消息

void pubMQTTmsg(){static int value; // 客户端发布信息用数字// 建立发布主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址。// 这么做是为确保不同用户进行MQTT信息发布时,ESP8266客户端名称各不相同,String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress();char publishTopic[topicString.length() + 1];  strcpy(publishTopic, topicString.c_str());// 建立发布信息。信息内容以Hello World为起始,后面添加发布次数。String messageString = "Hello World " + String(value++); char publishMsg[messageString.length() + 1];   strcpy(publishMsg, messageString.c_str());// 实现ESP8266向主题发布信息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."); }
}

收到信息后的回调函数

// 收到信息后的回调函数
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汇总

#include <ESP8266WiFi.h>
#include <PubSubClient.h>// 设置wifi接入信息(请根据您的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必须要设为false)const char* willTopic = "willTopic";    // 遗嘱主题名称
const char* willMsg = "willMsg";        // 遗嘱主题信息
const int willQos = 0;                  // 遗嘱QoS
const int willRetain = false;           // 遗嘱保留
const char* mqttUserName = "test-user"; // 服务端连接用户名
const char* mqttPassword = "ranye-iot"; // 服务端连接密码
//然也物联免费端口只提供这一个用户名密码
void setup() {pinMode(LED_BUILTIN, OUTPUT);     // 设置板上LED引脚为输出模式digitalWrite(LED_BUILTIN, HIGH);  // 启动后关闭板上LEDSerial.begin(9600);               // 启动串口通讯//设置ESP8266工作模式为无线终端模式WiFi.mode(WIFI_STA);// 连接WiFiconnectWifi();// 设置MQTT服务器和端口号mqttClient.setServer(mqttServer, 1883);mqttClient.setCallback(receiveCallback);// 连接MQTT服务器connectMQTTserver();
}void loop() {// 如果开发板未能成功连接服务器,则尝试连接服务器if (!mqttClient.connected()) {connectMQTTserver();}// 处理信息以及心跳mqttClient.loop();
}// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "client-" + WiFi.macAddress();/* 连接MQTT服务器boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); 若让设备在离线时仍然能够让qos1工作,则connect时的cleanSession需要设置为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);}
}// 收到信息后的回调函数
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(){// 建立订阅主题。使用然也物联的免费端口进行用户名密码连接时只能以"test-user/"开头// 这么做是为确保不同设备使用同一个MQTT服务器测试消息订阅时,所订阅的主题名称不同String topicString = "test-user/" + WiFi.macAddress();char subTopic[topicString.length() + 1];  strcpy(subTopic, topicString.c_str());// 通过串口监视器输出是否成功订阅主题以及订阅的主题名称// 请注意subscribe函数第二个参数数字为QoS级别。这里为QoS = 1if(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("");
}

【ESP8266教程】零基础入门学用物联网-基础知识篇(太极创客团队)学习笔记相关推荐

  1. 【太极创客】零基础入门学用Arduino 第一部分 合辑笔记

    [太极创客]零基础入门学用Arduino 第一部分 合辑 笔记大多整理于B站评论区 https://www.bilibili.com/video/BV164411J7GE/?spm_id_from=3 ...

  2. 零基础入门学Python(十二)—— 魔法方法(下)

    零基础入门学Python系列内容的学习目录→\rightarrow→零基础入门学Python系列内容汇总. 魔法方法(下) 1. 构造和析构 2. 算术运算 3. 简单定制 4. 属性访问 5. 描述 ...

  3. 跟艾文学编程《零基础入门学Python》(1)Python 基础入门

    作者: 艾文,计算机硕士学位,企业内训讲师和金牌面试官,现就职BAT一线大厂公司资深算法专家. 邮箱: 1121025745@qq.com 博客:https://wenjie.blog.csdn.ne ...

  4. 跟艾文学编程《零基础入门学Python》(4)Python 面向对象

    作者: 艾文,计算机硕士学位,企业内训讲师和金牌面试官,公司资深算法专家,现就职BAT一线大厂. 邮箱: 1121025745@qq.com 博客:https://wenjie.blog.csdn.n ...

  5. 零基础入门学Python(十二)—— 魔法方法(上)

    零基础入门学Python系列内容的学习目录→\rightarrow→零基础入门学Python系列内容汇总. 魔法方法(上) 1. 构造和析构 1.1 _ _ init _ _(self[, ...]) ...

  6. 跟艾文学编程 《零基础入门学Python》Jupyter Notebook安装和使用

    作者: 艾文,计算机硕士学位,企业内训讲师和金牌面试官,公司资深算法专家,现就职BAT一线大厂. 邮箱: 1121025745@qq.com 内容:跟艾文学编程<零基础入门学Python​​​​ ...

  7. esp8266灯上电闪一下_【零知ESP8266教程】快速入门2-点亮外部LED灯

    [零知ESP8266教程]快速入门2-点亮外部LED灯 [复制链接] 一.工具原料 电脑,windows系统 ESP8266开发板 micro-usb线 LED灯1个 220Ω 电阻1个 面包板一个+ ...

  8. [IOS APP]【现代流行唱法】零基础入门学唱歌

    本软件无广告,无内购,无后台,无求好评. 音频包括了<[现代流行唱法]零基础入门学唱歌> 40期节目. 更简单.更有效,让你零基础入门学唱歌.更快地提升唱歌水准,拥有万人瞩目的好声音!一起 ...

  9. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第三章:简单控件

    第 3 章 简单控件 本章介绍了App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图.容纳视图的常用布局.响应点击的按钮控件.显示图片的图像视图等.然后结合本章所学的知识,演示了一个实战项 ...

最新文章

  1. Go 语言的垃圾回收演化历程:垃圾回收和运行时问题
  2. 扩展 日历_2021少林日历 | 以最美的方式记录时光
  3. Angular js 具体应用(一)
  4. Rise of Shadows 闰年leap year-无法线性筛
  5. go map的定义及使用
  6. 我如何一分钱没花学完AI课程,入职新浪算法工程师
  7. C语言头文件 “ 细节 ”
  8. leetcode1433. 检查一个字符串是否可以打破另一个字符串(贪心算法)
  9. 前端学习(2003)vue之电商管理系统电商系统之之允许三级选择
  10. 0—1背包问题,回溯实现
  11. 多云时代-着眼布局开源技术之多云数据管理
  12. winpe装双系统linux_自制WINPE+MAC安装U盘及双系统存储U盘(增加多系统安装)
  13. matlab 双均线,[转载]百年一人的双均线系统及双均线系统公式
  14. Android 运行时权限
  15. WORD VBA实现查找带格式的文字并复制到特定地方
  16. 打开网站服务器显示403,打开网站显示403是什么意思
  17. IC Insights:2021年汽车和物联网芯片销售额将达到429亿美元
  18. 怎么把线稿提取出来_用ps如何提取线稿图?简单教程轻松搞定
  19. Google Play 开发者账号关联 如何解决
  20. 【产品人生】<基础认知>产品分析方法产品体验分析报告撰写

热门文章

  1. 毛哥的快乐生活(23) 我不装了!我摊牌了!我就是大神
  2. 仿哔哩哔哩动画Android客户端(哔哩哔哩 (゜-゜)つロ 干杯~-bilibili)
  3. Unity 插件之 AVPro Movie Capture Windows 录屏插件
  4. 1062- 49 个常用 CSS 样式清单整理
  5. java使用aspose实现文件预览工功能
  6. 预测中的各种数据处理
  7. 【微信小程序】-- 页面事件 - 上拉触底(二十六)
  8. 浏览器安装Copper插件
  9. Linux和DOS文件系统的区别,对比Linux文件系统和DOS文件系统
  10. FLIR数据集json文件转yolo格式txt (PS.coco数据集json文件转yolo格式txt)