前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、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那么NodeMCU
Serial.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地址
//--------"启动网络服务功能"程序部分开始-------- // 此部分为程序为本示例程序重点1
esp8266_server.begin(); // 详细讲解请参见太极创客网站《零基础入门学用物联网》
esp8266_server.on("/", handleRoot); // 第3章-第2节 ESP8266-NodeMCU网络服务器-1
esp8266_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引脚为输出模式以便控制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再启动后会扫描当前网络
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那么NodeMCU
Serial.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的IP
esp8266_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那么NodeMCU
Serial.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()){ // 启动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(); // 完成文件写入后关闭文件
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"即Append
dataFile.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(); //启动SPIFFS
Serial.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 // 按钮引脚D3
ESP8266WiFiMulti 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那么NodeMCU
Serial.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端口80
void 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那么NodeMCU
Serial.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请求,使用参数控制函数发送不同类型JSON
httpRequest(1);
delay(2000);
httpRequest(2);
delay(2000);
httpRequest(3);
delay(2000);
Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
// 向服务器发送HTTP请求,请求信息中包含json信息
void httpRequest(int jsonType){
// 建立WiFi客户端对象,对象名称client
WiFiClient client;
// 根据jsonType参数建立不同类型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;
// 通过串口输出连接服务器名称以便查阅连接服务器的网址
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 = 1
if(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.");
}
}
收到信息后的回调函数文章来源:https://www.toymoban.com/news/detail-861474.html
// 收到信息后的回调函数
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汇总文章来源地址https://www.toymoban.com/news/detail-861474.html
#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); // 启动后关闭板上LED
Serial.begin(9600); // 启动串口通讯
//设置ESP8266工作模式为无线终端模式
WiFi.mode(WIFI_STA);
// 连接WiFi
connectWifi();
// 设置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 = 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("");
}
到了这里,关于【ESP8266教程】零基础入门学用物联网-基础知识篇(太极创客团队)学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!