视频网址:https://www.bilibili.com/video/BV1L7411c7jw?p=13&spm_id_from=333.880.my_history.page.click&vd_source=b91967c499b23106586d7aa35af46413

程序网址:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/esp8266-client-sends-iot-data-to-esp8266-server/

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

1.1、使用ESP8266客户端向ESP8266服务器发送数据

硬件条件:一块 ESP8226 开发板作为客户端、一块 ESP8226 开发板作为服务器端。

esp8266如何发送数据到服务器 怎么给esp8266发送数据_http

实现功能:在这个示例中,ESP8266客户端将会通过HTTP协议向ESP8266服务器发送信息。在运行过程中,客户端ESP8266将会实时检测板上的按键状态,并且把按键状态发送给服务器。服务器在接收到客户端按键状态后,可以根据客户端按键状态来控制服务器端板上的LED点亮和熄灭。最终实现的效果是,我们可以通过客户端ESP8266开发板上的按键来“遥控”服务器上的LED点亮和熄灭。

esp8266如何发送数据到服务器 怎么给esp8266发送数据_http_02

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

需要规定通信要求:

客户端会向服务器端发送3个变量,一个是 int 类型的测试数据、一个是 float 类型的测试数据、还有一个是按键状态值。之后,服务器端定义三个变量来接收这三个变量,并做相应的处理。

客户端
/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : csd_client
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200228
程序目的/Purpose          : 
演示如何实现两个NodeMCU间通过WiFi进行通讯。两台NodeMCU一个以服务器模式运行,
一个以客户端模式运行。
 
此代码为客户端代码。此代码主要功能:
    - 通过HTTP协议向服务器发送HTTP请求
    - HTTP请求中包含客户端按键开关引脚状态和程序测试数据
-----------------------------------------------------------------------
修订历史/Revision History  
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
-----------------------------------------------------------------------
http信息发送说明
192.168.0.123/update?float=1.5&int=2&button=0
***********************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>   // 使用WiFiMulti库 
 
#define buttonPin D3            // 按钮引脚D3
 
ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是 'wifiMulti'
 
bool buttonState;       //存储客户端按键控制数据
float clientFloatValue; //存储客户端发送的浮点型测试数据
int clientIntValue;     //存储客户端发送的整数型测试数据
 
const char* host = "192.168.0.123";    // 即将连接服务器网址/IP
const int httpPort = 80;               // 即将连接服务器端口
 
void setup(void){
  Serial.begin(9600);                  // 启动串口通讯
  Serial.println("");
 
  pinMode(buttonPin, INPUT_PULLUP);    // 将按键引脚设置为输入上拉模式
  
  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 ...");                            // 则尝试使用此处存储的密码进行连接。
  
  while (wifiMulti.run() != WL_CONNECTED) { // 尝试进行wifi连接。
    delay(250);
    Serial.print('.');
  }
 
  // 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
}
 
void loop(void){
 // 获取按键引脚状态
 buttonState = digitalRead(buttonPin); 
 
 // 改变测试用变量数值用于服务器端接收数据检测
 clientFloatValue += 1.5;
 clientIntValue += 2;
 
 // 发送请求
 wifiClientRequest();
 delay(1000);
}
 
void wifiClientRequest(){
  WiFiClient client;  
 
  // 将需要发送的数据信息放入客户端请求
  String url = "/update?float=" + String(clientFloatValue) + 
               "&int=" + String(clientIntValue) +
               "&button=" + String(buttonState);
                         
  // 建立字符串,用于HTTP请求
  String httpRequest =  String("GET ") + url + " 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, httpPort)) {  //如果连接失败则串口输出信息告知用户然后返回loop
    Serial.println(" Sucess");
    
    client.print(httpRequest);          // 向服务器发送HTTP请求
    Serial.println("Sending request: ");// 通过串口输出HTTP请求信息内容以便查阅
    Serial.println(httpRequest);        
  } else{
    Serial.println(" failed");
  }
  
  client.stop();                         
}

客户端是如何将数据发送给服务器端的呢?

在客户端程序前的注释内容中,有 http 信息的发送说明:

192.168.2.44/update?float=1.5&int=2&button=0

这个说明是客户端在向服务器端发送请求的时候,它发送请求的地址信息。

这个地址信息包括服务器端的 ip 地址,/update 是通过请求这个地址页面信息,目的是让服务器调用函数 handleUpdate ,问号后面的内容是三个参数数值(通过 & 进行分隔的)。

最后,还需要补充一下关于 HTTP 协议方面的知识点。

在客户端中,使用 GET 来向服务器发送请求信息,可能会由此产生疑问,就是客户端想要从服务器获取信息时,我们使用 GET,而这里是向服务器发送信息,为什么发送信息和获取信息都使用 GET 呢 ?

实际上,在 http 协议中,没有非常严格的规定说哪一种操作必须要用哪一种方法。用 GET 既可以从服务器上获取信息,也可以向服务器上发送信息。

服务器端

实现功能:
1 – 接收客户端发来的http请求并且解析信息中的数据信息
2 – 将解析的数据信息通过串口监视器显示供用户查看
3 – 将解析的客户端按键状态信息用于控制服务器端板上LED的点亮和熄灭

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : csd_server
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20200228
程序目的/Purpose          : 
演示如何实现两个NodeMCU间通过WiFi进行通讯。两台NodeMCU一个以服务器模式运行,
一个以客户端模式运行。
 
此代码为客户端代码。此代码主要功能:
    - 接收客户端发来的http请求
    - 解析客户端请求中的数据信息
    - 将解析的数据信息通过串口监视器显示供用户查看
    - 将解析的客户端按键状态信息用于控制板上LED的点亮和熄灭
    
-----------------------------------------------------------------------
修订历史/Revision History  
日期/Date    作者/Author      参考号/Ref    修订说明/Revision Description
20200229      CYNO朔           0.01       加入IP设置
 
***********************************************************************/
 
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>   // 使用WiFiMulti库 
#include <ESP8266WebServer.h>   // 使用WebServer库
 
ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是 'wifiMulti'
 
ESP8266WebServer 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(void){
  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"); 
  } 
  
  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 ...");                            // 则尝试使用此处存储的密码进行连接。
  
  // 尝试进行wifi连接。
  while (wifiMulti.run() != WL_CONNECTED) { 
    delay(250);
    Serial.print('.');
  }
 
  // 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
 
  server.on("/update", handleUpdate);        // 处理服务器更新函数
  
  server.begin();                            // 启动网站服务
  Serial.println("HTTP server started");
}
 
void loop(void){
  server.handleClient();                    // 检查http服务器访问
}
 
void handleUpdate(){
  float floatValue = server.arg("float").toFloat();  // 获取客户端发送HTTP信息中的浮点数值
  int intValue = server.arg("int").toInt();        // 获取客户端发送HTTP信息中的整数数值
  int buttonValue = server.arg("button").toInt();  // 获取客户端发送HTTP信息中的按键控制量
  
  server.send(200, "text/plain", "Received");                 // 发送http响应
 
  buttonValue == 0 ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH);
 
  // 通过串口监视器输出获取到的变量数值
  Serial.print("floatValue = ");  Serial.println(floatValue);  
  Serial.print("intValue = ");  Serial.println(intValue); 
  Serial.print("buttonValue = ");  Serial.println(buttonValue);   
  Serial.println("=================");    
}

下面,来看下运行效果。

当开发板连接路由器后,通常路由器会给开发板动态分配一个 ip 地址,该 ip 地址是不固定的。如果我们想让其在连接 WiFi 后固定一个 ip 地址,应该如何操作呢?

在程序中,建立了四个 IPAddress 类型的对象,

IPAddress local_IP(192, 168, 2, 44); // 设置ESP8266-NodeMCU联网后的IP
IPAddress gateway(192, 168, 2, 1);    // 设置网关IP(通常网关IP是WiFI路由IP)
IPAddress subnet(255, 255, 255, 0);   // 设置子网掩码
IPAddress dns(192, 168, 2, 1);           // 设置局域网DNS的IP(通常局域网DNS的IP是WiFI路由IP)

通常来说,ip 地址使用点来分隔开,这里使用逗号来分隔开。

之后,再在程序下方使用 WiFi.config 来配置联网信息。

// 设置开发板网络环境
  if (!WiFi.config(local_IP, gateway, subnet)) {
    Serial.println("Failed to Config ESP8266 IP"); 
  }

这里只使用了 3 个,还缺少了 dns 这个对象,这是因为 dns 是一个可选参数,可有可无。

之后,使用尝试 WiFi 连接。在连接到 WiFi 之后,输出连接信息。

server.on("/update", handleUpdate);        // 处理服务器更新函数

是说,当有客户端请求开发板 /update 这个页面信息时,我们让其执行 handleUpdate 这个函数。

下面再来分析下 handleUpdate 这个函数。

float floatValue = server.arg("float").toFloat();  // 获取客户端发送HTTP信息中的浮点数值
  int intValue = server.arg("int").toInt();        // 获取客户端发送HTTP信息中的整数数值
  int buttonValue = server.arg("button").toInt();  // 获取客户端发送HTTP信息中的按键控制量

首先,定义三个变量,然后使用 server.arg 方法来进行解析和处理(数据类型转换)。

之后,

server.send(200, "text/plain", "Received");                 // 发送http响应

向客户端返回一个响应状态码,再向客户端返回一个 “Received” 的响应信息。

之后,根据解析出的按键状态值来控制本端(服务器端)的小灯状态。

最后,再通过串口监视器输出获取到的变量数值。

上述运行结果如下,

esp8266如何发送数据到服务器 怎么给esp8266发送数据_学习_03


此外,还可以使用浏览器来模拟这个操作。

在浏览器地址栏中输入

http://192.168.2.44/update?float=181.50&int=999&button=0

按下回车后,

esp8266如何发送数据到服务器 怎么给esp8266发送数据_物联网_04


同时,服务器端小灯会被点亮。

2、 客户端从服务器获取数据信息

2.1、使用ESP8266客户端向ESP8266服务器获取数据

程序链接: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/esp8266-client-gets-iot-data-from-esp8266-server/

需要注意:解析数据需要时间等待。

那有什么解决的方法吗?

这就引出了下面所讲的内容 JSON 。