《ESP8266 学习笔记》 TCP实践 之两个ESP8266通过TCP发送Json数据包并进行解析!

目录

1.简介:

2.硬件:

3.开发平台:

4.需要的库:

5.实验代码:

5.1 TCPClient端(负责JSON接收及解析):

5.2 TCPServer端(负责JSON打包及发送):

6.实验效果:


1.简介:

2019年夏季的全国大学生电子设计大赛中,我们组选择了电磁炮这个题目, 并且确定方案为STM32+OPENMV4(串口通讯),但当时苦于没有一个好的通信协议(毕竟当时还是小白~),只能选择了按位读取的办法,但在玩ESP8266这么久后突然想到各种物联网接入貌似都是用JSON来传输数据的,于是我便想到用各种方式来发送JSON数据(TCP、串口、IIC、UDP、各种你能想到的通信方式~),我们只需要解决Json的数据解析工作即可,令人高兴的是,Arduino方面我们有ArduinoJson库,STM32方面keil5也提供了官方的JSON库——Jansson,就算是其他单片机平台,也不要怕,我们还有开源C++编写的cJSON库,我们只需要简单移植,就可以让你的单片机使用JSON

2.硬件:

两个连接了0.96寸OLED的ESP8266开发板;

3.开发平台:

Arduino (1.8.10)     或     VScode 环境下 PlatformIO 插件

4.需要的库:

U8g2 :https://github.com/olikraus/U8g2_Arduino

ArduinoJson V5版本:https://github.com/bblanchon/ArduinoJson.git

5.实验代码:

5.1 TCPClient端(负责JSON接收及解析):

/**
 * @功能 两块ESP8266通过TCP发送Json消息并解析
 * @author 刘泽文
 * @date 2020/4/13
 * @TCP Client客户端
 */

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>
#include <Wire.h>

//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)      Serial.print(message)
#define DebugPrintf(message)     Serial.printf(message)

#define LED D4

const char* ssid = "liuzewen";
const char* password = "17609245102liu";

const char* Server = "192.168.31.53";
const int Port = 23;

short Status = 0;
uint8_t apple[60];
WiFiClient client;

//定义OLED型号
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

void setup() {
  DebugBegin(115200);

  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_wqy16_t_gb2312);
  u8g2.setCursor(40, 40);
  u8g2.print("Json解析");
  u8g2.sendBuffer();

  pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  DebugPrint("\nConnecting to "); 
  DebugPrintln(ssid);
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 20) {
    delay(500);
    DebugPrint("."); 
  }
  if (i == 21) {
    DebugPrint("Could not connect to"); 
    DebugPrintln(ssid);
    while (1) {
      delay(500);
    }
  }
 
  DebugPrint("Ready! Use 'telnet ");
  DebugPrint(WiFi.localIP());
}

void loop() {
  if(Status==0 && WiFi.status()==WL_CONNECTED)
  {
    Status=1;
    client.connect(Server, Port);
    DebugPrint("连接到服务器~");
  }

  while(client.available()){ 
    digitalWrite(LED,!digitalRead(LED));
    client.read(apple,60);
    StaticJsonBuffer<200> jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(apple);
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }
    const char* name = root["name"];
    int rand = root["rand"];
    double data = root["data"][0];
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_wqy16_t_gb2312);
    u8g2.setCursor(40, 16*1-2);
    u8g2.print("Json解析");
    u8g2.setCursor(0, 16*2-2);
    u8g2.print("name:");
    u8g2.setCursor(40, 16*2-2);
    u8g2.print(name);
    u8g2.setCursor(0, 16*3-2);
    u8g2.print("rand:");
    u8g2.setCursor(40, 16*3-2);
    u8g2.print(rand);
    u8g2.setCursor(0, 16*4-2);
    u8g2.print("data:");
    u8g2.setCursor(40, 16*4-2);
    u8g2.print(data);
    u8g2.sendBuffer();
    delay(200);

    if(!client.status()){
      DebugPrint("跳出循环");
      Status = 0;
      break;
    }
  }
}

5.2 TCPServer端(负责JSON打包及发送):

/**
 * @功能 两块ESP8266通过TCP发送Json消息并解析
 * @author 刘泽文
 * @date 2020/4/13
 * @TCP Server服务端
 */
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>
#include <Wire.h>

//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 2
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)      Serial.print(message)
#define DebugPrintf(message)     Serial.printf(message)

#define LED D4
 
const char* ssid = "liuzewen";
const char* password = "17609245102liu";
 
//创建server 端口号是23
WiFiServer server(23);
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];

//定义OLED型号
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
long pushtime = 0;

void setup() {
  DebugBegin(115200);

  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_wqy16_t_gb2312);
  u8g2.setCursor(40, 40);
  u8g2.print("Json发送");
  u8g2.sendBuffer();

  pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  DebugPrint("\nConnecting to "); 
  DebugPrintln(ssid);
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 30) {
    digitalWrite(LED,!digitalRead(LED));
    DebugPrint("."); 
    delay(500);
  }
  if (i == 21) {
    DebugPrint("Could not connect to"); 
    DebugPrintln(ssid);
    while (1) {
      delay(500);
    }
  }
  //启动server
  server.begin();
  //关闭小包合并包功能,不会延时发送数据
  server.setNoDelay(true);
 
  DebugPrint("Ready! Use 'telnet ");
  DebugPrint(WiFi.localIP());
  DebugPrintln(" 23' to connect");
  pushtime = millis();
}

void loop() {
  uint8_t i;
  //检测是否有新的client请求进来
  if (server.hasClient()) {
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //释放旧无效或者断开的client
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
        //分配最新的client
        serverClients[i] = server.available();
        DebugPrint("New client: "); 
        DebugPrint(i);
        break;
      }
    }
    //当达到最大连接数 无法释放无效的client,需要拒绝连接
    if (i == MAX_SRV_CLIENTS) {
      WiFiClient serverClient = server.available();
      serverClient.stop();
      DebugPrintln("Connection rejected ");
    }
  }

  //检测client发过来的数据
  for (i = 0; i < MAX_SRV_CLIENTS; i++) {
    if (serverClients[i] && serverClients[i].connected()) {
      if (serverClients[i].available()) {
        //get data from the telnet client and push it to the UART
        while (serverClients[i].available()) {
          //发送到串口调试器
          Serial.write(serverClients[i].read());
        }
      }
    }
  }
 
  if (Serial.available()) {
    //把串口调试器发过来的数据 发送给client
    size_t len = Serial.available();
    uint8_t sbuf[len];
    Serial.readBytes(sbuf, len);

    //给每个Client客户端发送数据
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        serverClients[i].write(sbuf, len);
        delay(1);
      }
    }
  }

  if(millis()-pushtime >= 500){
    digitalWrite(LED,!digitalRead(LED));
    pushtime = millis();
    int num = rand() % 130;
    // Json对象对象树的内存工具 静态buffer 
    // 200 是大小 如果这个Json对象更加复杂,那么就需要根据需要去增加这个值.
    StaticJsonBuffer<256> jsonBuffer;
    char json[60];
    // StaticJsonBuffer 在栈区分配内存   它也可以被 DynamicJsonBuffer(内存在堆区分配) 代替
    // DynamicJsonBuffer  jsonBuffer;
    //创建最外层的json对象 —— root对象,顶节点
    JsonObject& root = jsonBuffer.createObject();
    //给最外层json对象添加属性
    root["name"] = "liuzewen";
    root["rand"] = num;
    //在root对象中加入data数组
    JsonArray& data = root.createNestedArray("data");
    data.add(48.756080);
    data.add(2.302038);
    //root.printTo(server);
    //root.printTo(serverClients[0]);
    root.printTo(Serial);
    DebugPrintln();
    
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_wqy16_t_gb2312);
    u8g2.setCursor(40, 16*1-2);
    u8g2.print("Json发送");
    u8g2.setCursor(0, 16*2-2);
    u8g2.print("name:");
    u8g2.setCursor(40, 16*2-2);
    u8g2.print("liuzewen");
    u8g2.setCursor(0, 16*3-2);
    u8g2.print("rand:");
    u8g2.setCursor(40, 16*3-2);
    u8g2.print(num);
    u8g2.setCursor(0, 16*4-2);
    u8g2.print("date:");
    u8g2.setCursor(40, 16*4-2);
    u8g2.print("48.756080");
    u8g2.sendBuffer();
    sprintf(json, "{\"name\":\"liuzewen\",\"rand\":%d,\"data\":[48.756080,2.302038]}",num);
    int len = sizeof(json);
    //Serial.printf("缓存大小是:%d",sizeof("{\"name\":\"liuzewen\",\"rand\":200,\"data\":[48.756080,2.302038]}"));
    //给每个Client客户端发送数据
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        serverClients[i].write(json, len);
        //root.printTo(serverClients[i]);
        delay(1);
      }
    }
  }

}

6.实验效果:

猜你喜欢

转载自blog.csdn.net/qq_41868901/article/details/105528232