文章目录

  • 通过JSON实现物联网数据通讯
    • 1 ESP8266客户端请求JSON信息
      • 1.1 ESP8266客户端请求单一JSON数据信息
        • 1.1.1 服务器端程序
        • 1.1.2 客户端程序
    • 2 ESP8266客户端发送JSON信息
      • 2.1 ESP8266客户端发送单一JSON数据信息
        • 2.1.1 客户端
        • 2.1.2 服务器程序
      • 2.2 ESP8266客户端发送多种JSON数据信息

通过JSON实现物联网数据通讯

1 ESP8266客户端请求JSON信息

由于易于解析且量级很轻,JSON成为了常用的物联网信息传输格式之一。在这一节里,我们将一起学习以下几个主要知识点:

  1. 使用ESP8266来建立物联网服务器,该服务器可以向客户端发送JSON格式响应信息从而实现物联网信息通讯。
  2. 使用ESP8266来通过网络向物联网服务器请求JSON信息
  3. 使用ESP8266来通过ArduinoJson库解析JSON信息

在接下来的讲解中,我们将需要两块ESP8266-NodeMCU开发板。其中一块作为服务器,另一块作为客户端。如下图所示,客户端将会向服务器发送请求信息。服务器端在接收到客户端请求后,会将JSON信息加入服务器响应信息中发送给客户端。


注意,以下示例中的服务器端和客户端ESP8266必须连接同一WiFi网络,方可实现数据通讯。

1.1 ESP8266客户端请求单一JSON数据信息

本示例分为两部分,一部分为服务器程序,另一部分为客户端程序

1.1.1 服务器端程序

服务器端程序主要功能:

  1. 实时读取A0、 D1、D2以及D3引脚的读数。
  2. 当有客户端请求时,通过响应信息将引脚读数和测试数据信息发送给客户端。
    信息发送格式为json格式。以下为该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信息包含有三个数据,第一个数据”info”对应的值是一个包含有三个数据的对象。这三个数据值都是字符串格式。他们在整个程序运行中是保持不变的。第二个数据”digital_pin”所对应的值是一个含有三个数据的对象,这三个数据是ESP8266开发板的D1、D2、D3引脚的实时电平状态。其中D3引脚的状态正是NodeMCU开发板上按键的引脚状态。我们通过按下该按键,可以改变D3引脚电平状态。第三个数据”analog_pin”对应的值是一个含有一个数据的对象。该数据是ESP8266的模拟输入引脚实时读数。换句话说, “digital_pin”和”analog_pin”所对应的数据值都是ESP8266引脚的实时状态,这些信息是会改变的。

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : cgj_server_1
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 2020305
程序目的/Purpose          :
本实例用于演示esp8266的json数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端。
本程序为服务器程序,功能如下:1. 实时读取A0、 D1、D2以及D3引脚的读数。
2. 当有客户端请求信息时,将会通过http响应将引脚读数等信息发送给客户端。信息发送格式为json格式。
3. 本程序使用了wifi.config对开发板的IP进行了配置。
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200511      CYNO朔           001        1 移除handleNotFound使教程代码更加精简2 改请求路径为update
***********************************************************************/
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h>   //  ESP8266WiFiMulti库
#include <ESP8266WebServer.h>   //  ESP8266WebServer库#define buttonPin D3            // 按钮引脚D3ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)IPAddress local_IP(192, 168, 0, 123); // 设置ESP8266-NodeMCU联网后的IP
IPAddress gateway(192, 168, 0, 1);    // 设置网关IP(通常网关IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0);   // 设置子网掩码
IPAddress dns(192,168,0,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("taichi-maker1", "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地址esp8266_server.on("/", handleRoot);          esp8266_server.begin();  Serial.println("HTTP esp8266_server started");//  告知用户ESP8266网络服务功能已经启动
}void loop(){// 处理http服务器访问esp8266_server.handleClient();
}                                                                   void handleRoot() {   //处理网站目录“/”的访问请求 esp8266_server.send(200, "application/json", rootJson());
}// 实时获取ESP8266开发板引脚信息并且建立JSON信息
// 以便ESP8266服务器通过响应信息发送给客户端
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;
}

以上程序的重点是函数rootJson。该函数作用是实时获取ESP8266开发板引脚信息并且建立JSON信息。该信息将会通过服务器响应信息发送给请求这一信息的客户端。此方法相对简单,但是缺点是不够灵活。假如我们需要修改响应的JSON信息,那么就要重新构建JSON字符串。另外,假如我们的响应JSON信息比较复杂,那么构建这个字符串的工作还是很麻烦的。接下来我们再以上程序的基础上做一下修改。我们将使用ArduinoJson官网的在线工具来自动生成代码,搭建我们想要的JSON信息并应用到程序的rootJson函数中。

/**********************************************************************
项目名称/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, 0, 123); // 设置ESP8266-NodeMCU联网后的IP
IPAddress gateway(192, 168, 0, 1);    // 设置网关IP(通常网关IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0);   // 设置子网掩码
IPAddress dns(192,168,0,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("taichi-maker1", "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地址esp8266_server.begin();                  esp8266_server.on("/", handleRoot);          Serial.println("HTTP esp8266_server started");//  告知用户ESP8266网络服务功能已经启动
}void loop(){// 处理http服务器访问esp8266_server.handleClient();
}                                                                   void handleRoot() {   //处理网站目录“/”的访问请求 esp8266_server.send(200, "application/json", rootJson());
}// 实时获取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;
}

1.1.2 客户端程序

客户端程序的主要功能:

  1. 向服务器端请求json数据信息
  2. 解析服务器端响应的json信息内容。
  3. 将解析后的数据信息显示于串口监视器
  4. 利用服务器端D3引脚(按键引脚)读数来控制客户端开发板上LED的点亮和熄灭
/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : cgj_client_1
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200228
程序目的/Purpose          :
本实例用于演示esp8266的json数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端。
本程序为客户端程序,功能如下:1. 通过http协议向服务器端请求json数据信息
2. 解析服务器端响应的json信息内容。
3. 将解析后的数据信息显示于串口监视器
4. 利用服务器端D3引脚(按键引脚)读数来控制客户端开发板上LED的点亮和熄灭
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200302      CYNO朔           001        添加arduinojson解析错误识别
20200511      CYNO朔           002        改请求路径为update
20200511      CYNO朔           003        parse过程使用函数完成
***********************************************************************/
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>ESP8266WiFiMulti wifiMulti;           // 建立ESP8266WiFiMulti对象const char* host = "192.168.0.123";   // 将要连接的服务器地址
const int httpPort = 80;              // 将要连接的服务器端口      void setup(){Serial.begin(9600);          Serial.println("");// 设置开发板LED引脚pinMode(LED_BUILTIN, OUTPUT);digitalWrite(LED_BUILTIN, HIGH);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) { // 尝试进行wifi连接。delay(1000);Serial.print(i++); Serial.print(' ');}// WiFi连接成功后将通过串口监视器输出连接成功信息 Serial.println("");Serial.print("Connected to ");Serial.println(WiFi.SSID());              // WiFi名称Serial.print("IP address:\t");Serial.println(WiFi.localIP());           // IP
}void loop(){httpRequest();delay(3000);
}// 向服务器请求信息并对信息进行解析
void httpRequest(){WiFiClient client;String httpRequest = String("GET /") + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n";Serial.print("Connecting to "); Serial.print(host);if (client.connect(host, 80)){Serial.println(" Success!");// 向服务器发送http请求信息client.print(httpRequest);Serial.println("Sending request: ");Serial.println(httpRequest);  // 获取并显示服务器响应状态行 String status_response = client.readStringUntil('\n');Serial.print("status_response: ");Serial.println(status_response);// 使用find跳过HTTP响应头if (client.find("\r\n\r\n")) {Serial.println("Found Header End. Start Parsing.");}parseInfo(client); }else {Serial.println(" connection failed!");}   //断开客户端与服务器连接工作client.stop();
}void parseInfo(WiFiClient client){const size_t capacity = JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(3) + 140;DynamicJsonDocument doc(capacity);deserializeJson(doc, client);JsonObject info = doc["info"];const char* info_name = info["name"]; // "taichimaker"const char* info_url = info["url"]; // "www.taichi-maker.com"const char* info_email = info["email"]; // "taichimaker@163.com"JsonObject digital_pin = doc["digital_pin"];const char* digital_pin_d1 = digital_pin["d1"]; // "1"const char* digital_pin_d2 = digital_pin["d2"]; // "0"const char* digital_pin_d3 = digital_pin["d3"]; // "1"const char* analog_pin_a0 = doc["analog_pin"]["a0"]; // "500"String info_name_str = info["name"].as<String>();bool d3_bool = digital_pin["d3"].as<int>();Serial.print("info_name_str = ");Serial.println(info_name_str);Serial.print("d3_bool = ");Serial.println(d3_bool);d3_bool == 0 ? digitalWrite (LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH);
}

以上程序中最重点的部分是函数httpRequest。该函数向服务器发送HTTP请求,并且对服务器相应的JSON信息进行了解析。解析后的数据信息将通过串口监视器显示,其中服务器按键引脚的状态信息还被用于控制客户端板上的LED点亮和熄灭。

2 ESP8266客户端发送JSON信息

客户端将会向服务器发送请求信息。在客户端的请求信息中将会包含JSON信息。服务器接收到请求信息后,会从请求信息中获取JSON信息,并且解析该JSON中的内容。


注意,以下示例中的服务器端和客户端ESP8266必须连接同一WiFi网络,方可实现数据通讯。

2.1 ESP8266客户端发送单一JSON数据信息

本示例程序分为两部分,一部分为服务器程序,另一部分为客户端程序。

2.1.1 客户端

客户端程序主要功能:

  1. 实时读取A0、 D1、D2以及D3引脚的读数。
  2. 向服务器发送Json信息。发送的信息中包含有D3引脚状态从而控制服务器开发板上
    的LED点亮或熄灭。以下为该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"}
}
/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : csj_client_one_json
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : Dapenson
日期/Date(YYYYMMDD)     : 20200425
程序目的/Purpose          :
本实例用于演示esp8266的json数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端本程序为客户端程序,功能如下:
1. 实时读取A0、 D1、D2以及D3引脚的读数。
2. 向服务器发送Json信息。发送的信息中包含有D3引脚状态从而控制服务器开发板上的LED点亮或熄灭
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200520      CYNO朔           001        修改httpRequest将两个“/r/n”合并
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>ESP8266WiFiMulti wifiMulti;           // 建立ESP8266WiFiMulti对象const char* host = "192.168.0.123"; // 网络服务器地址
const int httpPort = 80;            // http端口80void setup(){Serial.begin(9600);          Serial.println("");//通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("taichi-maker1", "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地址
}void loop(){// 发送HTTP请求httpRequest();    delay(3000);
}// 向服务器发送HTTP请求,请求信息中包含json信息
void httpRequest(){// 建立WiFi客户端对象,对象名称clientWiFiClient client;    // 重点1: 建立JSON,此JSON包含需要发送的信息String payloadJson = "{\"info\": {\"name\": \"taichimaker\",\"url\": \"www.taichi-maker.com\",\"email\": \"taichimaker@163.com\"},\"digital_pin\": {\"d1\": \"";payloadJson += String(digitalRead(D1));  payloadJson += "\",\"d2\": \""; payloadJson += String(digitalRead(D2));  payloadJson += "\",\"d3\": \""; payloadJson += String(digitalRead(D3));  payloadJson += "\"},\"analog_pin\": {\"a0\": \"";payloadJson += String(analogRead(A0));payloadJson += "\"}}";  // 建立字符串,用于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);
}

重点部分讲解:
请留意以上程序重点1部分。这里我们实时读取开发板各个引脚状态并且将这些引脚读数放在payloadJson字符串中,然后将其放入httpRequest字符串中发送给服务器。

2.1.2 服务器程序

以下示例程序将会利用WiFiServer库建立ESP8266网络服务器。我们可以通过网页浏览器客户端访问该服务器。客户端的请求信息将会通过ESP8266的串口输出以便我们观察程序 运行状况。
了解WiFiServer库的基本操作

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : wifiServer_example
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200521
程序目的/Purpose          :
本实例用于演示如何使用WiFiServer库利用ESP8266开发板建立基本网络服务器。
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/
***********************************************************************/
#include <ESP8266WiFi.h>const char* ssid = "taichimaker";
const char* password = "12345678";WiFiServer server(80);void setup() {Serial.begin(9600);Serial.println();WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(F("."));}// 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地址// 启动服务器server.begin();
}void loop() {runServer();  // 运行服务器
}void runServer(){// 建立WiFiClient对象用于处理客户端请求信息WiFiClient incomingClient = server.available();// 如果没有客户端请求信息,则“跳过”函数中后续程序内容if (!incomingClient) {return;}Serial.println("====Client  Connected===");// 通过串口监视器输出客户端请求信息String clientRequest = incomingClient.readString();Serial.print(clientRequest);// 建立服务器响应信息String httpResponse ="HTTP/1.0 200 OK\r\n""Connection: close\r\n""Content-Type: text/plain;\r\n""\r\n""client_request_received";// 向客户端发送以上服务器响应信息incomingClient.print(httpResponse); incomingClient.stop();  Serial.println("incomingClient stop");
}

掌握了如何使用WiFiServer库来获取客户端请求信息后,接下来我们开始学习服务器端示例程序。该程序将会实现以下功能。

  1. 获取客户端请求信息中的json
  2. 解析json信息内容
  3. 将解析后的数据信息显示于串口监视器
  4. 利用json中客户端D3引脚(按键引脚)读数来控制服务器端开发板上LED的点亮和熄灭
/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : csj_server
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200425
程序目的/Purpose          :
本实例用于演示esp8266的json数据通讯。
操作测试本程序需要使用两台8266开发板。其中一台为服务器端,一台为客户端。
本程序为服务器程序,功能如下:1. 获取客户端请求信息中的json。
2. 解析json信息内容。
3. 将解析后的数据信息显示于串口监视器
4. 利用json中客户端D3引脚(按键引脚)读数来控制服务器端开发板上LED的点亮和熄灭
-----------------------------------------------------------------------
修订历史/Revision History
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200520      CYNO朔           001        修改parseInfo部分,使其与cgj_client_2更加一致
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <ESP8266WiFiMulti.h>   ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'IPAddress local_IP(192, 168, 0, 123); // 设置ESP8266-NodeMCU联网后的IP
IPAddress gateway(192, 168, 0, 1);    // 设置网关IP(通常网关IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0);   // 设置子网掩码
IPAddress dns(192,168,0,1);           // 设置局域网DNS的IP(通常局域网DNS的IP是WiFI路由IP)// 建立WiFiServerSecure对象
WiFiServer server(80);void setup() {Serial.begin(9600);Serial.println();pinMode(LED_BUILTIN, OUTPUT);digitalWrite(LED_BUILTIN, HIGH);// 设置开发板网络环境if (!WiFi.config(local_IP, gateway, subnet)) {Serial.println("Failed to Config ESP8266 IP"); } //通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("taichi-maker1", "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地址// 启动服务器server.begin();
}void loop() {runServer();  // 运行服务器
}// 运行服务器
void runServer(){// 重点1:建立WiFiClient对象用于处理客户端请求信息WiFiClient incomingClient = server.available();// 如果没有客户端连接服务器,则“跳过”本函数中后续程序内容if (!incomingClient) {return;}Serial.println("====Client  Connected===");// 重点2:如果有客户端连接服务器,则尝试使用find跳过HTTP请求头if (incomingClient.find("\r\n\r\n")) {Serial.println("Found Header End. Start Parsing.");}// 解析请求体中的json信息 parseInfo(incomingClient);// 建立服务器响应信息String httpResponse ="HTTP/1.0 200 OK\r\n""Connection: close\r\n""Content-Type: text/plain;\r\n""\r\n""client_message_received";// 向客户端发送以上服务器响应信息incomingClient.print(httpResponse); incomingClient.stop();  Serial.println("incomingClient stop");
}// 重点3:解析请求体中的json信息
void parseInfo(WiFiClient client){bool d3_bool;          // 建立变量存储客户端开发板按键信息String info_name_str;  // 建立变量存储字符串信息int analog_pin_a0_int; // 建立变量存储客户端开发板模拟输入引脚读数const size_t capacity = JSON_OBJECT_SIZE(1) + 3*JSON_OBJECT_SIZE(3) + 140;DynamicJsonDocument doc(capacity);deserializeJson(doc, client);JsonObject info = doc["info"];if(info){Serial.println("Server Json has info: true");const char* info_name = info["name"];const char* info_url = info["url"];const char* info_email = info["email"];info_name_str =  info["name"].as<String>();Serial.print("info_name_str = ");Serial.println(info_name_str);} else {Serial.println("Server Json has info: false");}JsonObject digital_pin = doc["digital_pin"];if (digital_pin){Serial.println("Server Json has digital_pin: true");const char* digital_pin_d1 = digital_pin["d1"]; const char* digital_pin_d2 = digital_pin["d2"]; const char* digital_pin_d3 = digital_pin["d3"];d3_bool = digital_pin["d3"].as<int>();Serial.print("d3_bool = ");Serial.println(d3_bool);} else {Serial.println("Server Json has digital_pin: false");}const char* analog_pin_a0 = doc["analog_pin"]["a0"]; if (analog_pin_a0){Serial.println("Server Json has analog_pin_a0: true");analog_pin_a0_int = doc["analog_pin"]["a0"].as<int>(); Serial.print("analog_pin_a0 = ");Serial.println(analog_pin_a0);} else {Serial.println("Server Json has analog_pin_a0: false");}// 利用d3引脚读数控制板上LED点亮和熄灭d3_bool == 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH);
}

程序重点部分讲解:
重点1:建立WiFiClient对象用于处理客户端请求信息
当有客户端连接到服务器后,我们可以使用此处建立的WiFiClient对象来处理客户端所发送的请求信息。

重点2:如果有客户端向服务器发送请求信息,则尝试跳过客户端请求头信息。此处我们使用了incomingClient.find(“\r\n\r\n”)来查找请求头结尾。
一旦查找到请求头结尾部分,后续的信息就是客户端请求体了。在请求体中的正是客户端发来的json信息。

重点3:解析请求体中的json信息
parseJson函数的作用是解析客户端发送的JSON信息。这一操作没有过多需要讲解的,因为我们在以前的示例中已经多次出现这一操作。需要特别提出的是在解析JSON信息时,我们使用了一系列if判断语句来判断JSON信息中是否包含有相应的键。比如如下语句:

Arduinoif (info){Serial.println("Server Response JSON contains key info: true");info_name_str = info["name"].as<String>();Serial.print("info_name_str = ");Serial.println(info_name_str);} else {Serial.println("Server Response JSON contains key info: false");}

这里使用了if(info)来判断客户端JSON信息中是否有info这一键。如果有,我们就会对它实施进一步操作。如果没有则通过串口监视器告知用户,客户端发送的JSON中没有info键。

2.2 ESP8266客户端发送多种JSON数据信息

以上这一操作利用了字符串来建立客户端请求。这么做很简单直接,但是缺点是不够灵活。试想我们建立的物联网项目中,客户端连接有大量传感器,并且每当任何一个传感器发生变化都要将所有传感器信息上传服务器。这么做会浪费大量网络资源和运算资源。接下来我们看如何操作让客户端只将一部分信息上传服务器。

/**********************************************************************
项目名称/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.0.123"; // 网络服务器地址
const int httpPort = 80;            // http端口80void setup(){Serial.begin(9600);          Serial.println("");//通过addAp函数存储  WiFi名称       WiFi密码wifiMulti.addAP("taichi-maker1", "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地址
}void loop(){// 发送HTTP请求,使用参数控制函数发送不同类型JSONhttpRequest(1);    delay(2000);httpRequest(2); delay(2000); httpRequest(3); delay(2000);
}// 向服务器发送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);
}//建立json信息
String buildJson(int type){// 开始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("json Code: ");Serial.println(jsonCode); return jsonCode;
}

以上示例中的buildJson函数中,我们针对3个不同情况构建了3种不同的JSON信息。这里我们使用了ArduinoJson库的createNestedObject函数以及serializeJson函数来实现。

示例二中的服务器程序与示例一服务器程序可以通用。所以这里就不再重复这一程序内容了。

内容来自 -----> 太极创客
详情可见太极创客官网,内有Arduino、ESP32等详细教程
http://www.taichi-maker.com

【ESP32_8266_WiFi (十一)】通过JSON实现物联网数据通讯相关推荐

  1. 学习太极创客 — ESP8226 (八)JSON 数据通讯 二

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=17&vd_source=b91967c499b23106586d7aa35af46413 ...

  2. 学习太极创客 — ESP8226 (七)JSON 数据通讯 一

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=16&vd_source=b91967c499b23106586d7aa35af46413 ...

  3. 使用WIFI模块与阿里云物联网套件进行透传数据通讯(M0E1系列)

    使用WIFI模块与阿里云物联网套件进行透传数据通讯(M0E1系列) 前言 具体步骤 进入AT指令模式 配置相应的AT指令 简单测试 阿里去物联网套件控制模块引脚功能 说明 前言 M0E1系列模组,是基 ...

  4. 学习太极创客 — ESP8226 (九)JSON 数据通讯 三

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=18&vd_source=b91967c499b23106586d7aa35af46413 ...

  5. 使用WIFI模块与MQTT服务器进行透传数据通讯(M0E1系列)

    使用WIFI模块与百度天工进行透传数据通讯(M0E1系列) 前言 具体步骤 进入AT指令模式 配置相应的AT指令 使用MQTT.fx进行测试 MQTT控制模块引脚功能 说明 前言 M0E1系列模组,是 ...

  6. 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)

    今天没有延续上一篇讲的内容,穿插一段小插曲,WebSocket 实时数据通讯同步的问题,今天我们并不是很纯粹地讲 WebSocket 相关知识,我们通过 WebGL 3D 拓扑图来呈现一个有趣的 De ...

  7. grafana模板_EMQ X + InfluxDB + Grafana:物联网数据监控可视化方案

    本文以常见物联网使用场景为例,介绍了如何利用 EMQ X 消息中间件与开源数据可视化方案 InfluxDB + Grafana ,将物联网设备大量基于时序的数据便捷地展示出来. 在物联网项目中接入平台 ...

  8. emqx 使用端口_数据传输、存储、展现,EMQ X + TDengine 搭建 MQTT 物联网数据可视化平台...

    物联网数据采集涉及到大量设备接入.海量的时序数据传输,EMQ X 消息中间件与 TDengine 大数据平台的组合技术栈完全能够胜任场景中的海量时间序列监测数据的传输.存储和计算. 数据入库后,往往需 ...

  9. 连物联网数据都理不清楚还怎么搞大数据分析?

    http://iot.ofweek.com/2017-04/ART-132214-8120-30122147.html 数据即价值是目前计算机领域极其推崇的观念.数据无论多少都被归结为大数据,数据分析 ...

最新文章

  1. mysql 计算排名,生成排行榜
  2. 用json 数据生成mysql 表_根据json数据生成表格
  3. Redis数据库的管理
  4. 推荐系统相关算法(1):SVD
  5. 爬虫图片href是html图片,xpath爬虫实例,爬取图片网站百度盘地址和提取码
  6. 从框架源码中学习创建型设计模式
  7. MITx - 6.00.1x 笔记(4) Good Programming Practices
  8. 【华为云技术分享】干货!!卷积神经网络之LeNet-5迁移实践案例
  9. APUE 学习笔记(十) 高级I/O
  10. 剑指offer面试题[21]包含min函数的栈
  11. Fixjs——事件回调的this
  12. 前向声明include区别
  13. 拓端tecdat|R语言曲线回归:多项式回归、多项式样条回归、非线性回归数据分析
  14. eclipse安装教程2020版(解决官网下载的安装包打开无响应的问题)
  15. 怎么用计算机求正切值的角度,在excel中如何使用正切函数计算,excel函数tan怎么反算角度...
  16. Office 检测到一个与此文件相关的问题为帮助保护您的计算机,无法打开此文件。
  17. 英雄联盟|王者|穿越火线 bgm AI配乐大赛分享
  18. 威斯康星大学-机器学习导论2020
  19. 线程池 (通俗易懂)
  20. 微型linux系统测试网卡,自制一个小型Linux(附带网络功能)

热门文章

  1. js给label赋值功能
  2. 科技巨头Software AG遭攻击,关闭445高危端口后,Windows共享用不了,怎么办?
  3. 中国民营医疗产业经营管理模式与“十四五”发展规划建议报告2021-2027年版
  4. rabbitMQ集群异常
  5. 寻找中国最好百名产品经理:豆瓣阿北360周鸿祎
  6. Python 可视化神器--Plotly
  7. 深圳市地方金融监督管理局支持黄金珠宝消费券试点“数字货币”
  8. 宗镜录略讲——南怀瑾老师——系列1
  9. Java、JSP网上报名系统
  10. 基于机器学习的服装搭配问题分析