个人笔记:ESP8266发送POST请求调用API的一种方法

您所在的位置:网站首页 esp8266代码加密 个人笔记:ESP8266发送POST请求调用API的一种方法

个人笔记:ESP8266发送POST请求调用API的一种方法

2023-04-02 21:15| 来源: 网络整理| 查看: 265

目录

前言:

TinyWebDB

代码讲解

整体代码

前言:

硬件:ESP8266主板、数据线

编译器:Arduino IDE

需要的库: 

TinyWebDB

        TinyWebDB是一个非关系型数据库,它的数据结构是键值对(Key-Value)结构。在TinyWebDB中,每个数据项都有一个键和一个对应的值,键值对之间没有固定的关系,可以随时添加、删除和修改。TinyWebDB的数据库结构可以简单地表示为:

{

  "key1": "value1",

  "key2": "value2",

  "key3": "value3",

  ...

}

        其中,"key1"、"key2"、"key3"等表示键名,"value1"、"value2"、"value3"等表示对应的值。这种数据结构非常简单,但也非常灵活,可以存储各种不同类型的数据,包括字符串、数字、布尔值等。

        在TinyWebDB中,每个数据项的键名是唯一的,如果添加了重复的键名,后面的键值会覆盖前面的键值。这种设计可以保证数据的唯一性和正确性。同时,由于TinyWebDB的数据结构非常简单,因此可以很方便地进行数据的查询、修改和删除操作。

        总的来说,TinyWebDB的数据库结构非常简单,由键值对组成,这种设计具有灵活性和高效性,非常适合存储小规模的数据。TinyWebDB本是用于APP Inventor中的网络微数据库,但由于其简洁、轻量且免费,所以在此项目中被用来作为POST请求的操作对象。

以下是TinyWebDB服务器的网址,可以自行注册登录使用:

TinyWebDB服务器 - APPInventor网络微数据库http://tinywebdb.appinventor.space/

        注册并登录后记住以下信息:

                API地址:http://tinywebdb.appinventor.space/api

                用户名(user):your_username

                密钥(secret):your_secret

                以及各种操作与各种参数要求。

代码讲解

首先是库的导入:

#include #include

        该段代码使用了ESP8266WiFi和ArduinoJson两个库。

        其中ESP8266WiFi库用于连接Wi-Fi网络,ArduinoJson库用于解析JSON格式的数据。

以及一些字段的定义:

const char* ssid = "Wifi_ID"; const char* password = "Wifi_password"; const char* host = "tinywebdb.appinventor.space"; // TinyWebDB的API地址 const int httpPort = 80; String user = "your_username"; String secret = "your_secret";

        其中的 "Wifi_ID";  "Wifi_password";  "your_username";  "your_secret";要填入对应的字段。

        分别对应的是你的Wifi名称、Wifi密码、TinyWebDB用户名(user)以及密钥(secret)

        /*应该不会看不懂吧*/

接着是setup函数的内容

void setup() { Serial.begin(9600); delay(1000); WiFi.begin(ssid, password); delay(2000); Serial.print("Connecting to WiFi "); Serial.print(ssid); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(" "); Serial.print("Connected to WiFi: "); Serial.println(ssid); Serial.println(" "); Serial.print("Select your action (update/ get/ delate/ count/ search/ show): "); }

        这里除了一些必要的代码外,还做了一些串口端的文字提示内容,如果不需要可以直接删除。

        实际效果如下图: 

个人认为应该在一切有人机交互的地方加入合理的设计

 然后是loop函数的内容

void loop() { if (Serial.available()) { String input = Serial.readStringUntil('\n'); Serial.println(input); input.trim(); if (input == "update"){updateValue();} //添加或更新 else if (input == "get"){getValue();} //读取 else if (input == "delete"){deleteValue();} //删除 else if (input == "count"){countValues();} //计数 else if (input == "search"){searchValues();} //查询 else if (input == "show"){showDB();} //显示全部(100条为上限) else { Serial.println("Invalid command."); //非法指令 } Serial.print("\nSelect your action (update/ get/ delate/ count/ search/ show): "); } }

        通过六种不同的串口输入会有六种对应的操作,总体来说就是增删改查,我们会通过六个不同的函数来实现各自的功能。

        这里还会涉及到一些关于串口字符串读取与判断的语句,在此不多讲,关于串口通信如有必要会专门写一篇。

        在六种函数中,updateValue、deleteValue大多数情况下是不需要返回值的,而其他的函数都会有JSON格式的返回值,其中有countValues这种我们需要提取一个字符串+一个整型值的,也有searchValues、getValue以及showDB这种我们需要提取一(多)个字符串+一(多)个对应字符串的情况,所以我们将从updateValue()、searchValues()、countValues()三个函数的角度进行讲解。

⭐updateValue操作函数

void updateValue(){ String tag, value; Serial.print("Enter tag: "); while (!Serial.available()) {} tag = Serial.readStringUntil('\n'); Serial.println(tag); tag.trim(); Serial.print("Enter value: "); while (!Serial.available()) {} value = Serial.readStringUntil('\n'); Serial.println(value); value.trim(); if (tag.length() > 0 && value.length() > 0) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=update&tag=" + tag + "&value=" + value; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Server response:"); Serial.println(" "); while (client.connected()) { String line = client.readStringUntil('\n'); Serial.println(line); if (line == "\r") { break; } } Serial.println("Update Done."); } }

        通过询问需要添加条目的tag以及value(也就是键名和对应的值),发送对应的POST请求。

        在这一段中,该代码首先创建了一个WiFiClient对象client,然后使用client.connect()方法连接到指定的主机和端口。如果连接失败,则输出“connection failed”并返回。

        接下来,该代码构造了一个URL,并使用client.print()方法发送HTTP请求。

        其中,HTTP请求的第一行为“POST URL HTTP/1.1”,表示使用POST方法发送请求。请求头中包含了主机名、连接方式和空行。

        发送完请求后,该代码使用client.readStringUntil()方法读取响应数据,并在读到空行时停止。

        最终,响应数据被存储在line字符串变量中。

        需要注意的是,输出的内容是可以通过注释掉对应的Serial.println()进行筛选的,例如我自己在使用时是不会显示line中的响应数据的,此处为了展示所以保留,但在后续的函数中将不再显示。

        实际效果如下图: 

         而此时我的数据库中就多了这么一条数据:

 ⭐searchValues操作函数

void searchValues(){ String no, count; Serial.print("Search from NO: "); while (!Serial.available()) {} no = Serial.readStringUntil('\n'); Serial.println(no); no.trim(); Serial.print("Total count: "); while (!Serial.available()) {} count = Serial.readStringUntil('\n'); Serial.println(count); count.trim(); if (no.length() > 0 && count.length() > 0) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=search&no=" + no + "&count=" + count; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.println("Search Result:"); for (JsonPair pair : obj) { String tag = pair.key().c_str(); //float value = pair.value().as(); String value = pair.value().as(); Serial.print("Tag: "); Serial.print(tag); Serial.print(" Content: "); Serial.println(value); } } }

        其中与updateValue函数结构重复的部分就不再进行说明。

        需要说明的是对返回值中JSON数据的提取和处理。

        先定义了起始和结束位置的变量start和end,然后通过response字符串中的indexOf()和lastIndexOf()函数找到JSON数据的起始和结束位置。

        接着,通过substring()函数获取JSON数据的字符串形式,存储在json变量中。

        然后,使用deserializeJson()函数将json解析成DynamicJsonDocument类型的对象doc。

        接下来,将doc转化成JsonObject类型的对象obj,通过遍历obj中的每一个元素,获取每个元素的key和value并输出。

        需要注意的是这里,如果你的数据库中所有的value值都是数字,那么你可以通过float value = pair.value().as();直接提取出浮点型或者通过int value = pair.value().as();直接提取出整型,但大多数情况下我不推荐这么做,因为数据在上传时并没有对value的类型做出任何要求,那么在读取时应当认为它有可能是字符串类型,否则会有意外的读取错误的情况发生。

      //float value = pair.value().as();       String value = pair.value().as();

        这一点在countValues函数中有所体现。

 ⭐countValues操作函数

void countValues(){ // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=count"; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.print("Count Result: "); for (JsonPair pair : obj) { String count = pair.key().c_str(); int value = pair.value().as(); //Serial.print("Count: "); //Serial.print(count); //Serial.print(" Value: "); Serial.println(value); } }

        与前两个函数类似的部分就不再赘述。

        可以看到,由于countValues操作返回的value是数据的总条目数,而数据的总条目数必然是一个整数,所以我在提取元素时便直接将这里的value作为整型变量(int)进行操作了。

        这种对于JSON数据的处理方式也可以灵活运用于Arduino IDE编程中的其他地方。

整体代码 #include #include const char* ssid = "Wifi_ID"; const char* password = "Wifi_password"; const char* host = "tinywebdb.appinventor.space"; // TinyWebDB的API地址 const int httpPort = 80; String user = "your_username"; String secret = "your_secret"; void setup() { Serial.begin(9600); delay(1000); WiFi.begin(ssid, password); delay(2000); Serial.print("Connecting to WiFi "); Serial.print(ssid); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(" "); Serial.print("Connected to WiFi: "); Serial.println(ssid); Serial.println(" "); Serial.print("Select your action (update/ get/ delate/ count/ search/ show): "); } void loop() { if (Serial.available()) { String input = Serial.readStringUntil('\n'); Serial.println(input); input.trim(); if (input == "update") { updateValue(); } else if (input == "get") { getValue(); } else if (input == "delete") { deleteValue(); } else if (input == "count") { countValues(); } else if (input == "search") { searchValues(); } else if (input == "show") { showDB(); } else { Serial.println("Invalid command."); } Serial.print("\nSelect your action (update/ get/ delate/ count/ search/ show): "); } } void updateValue(){ String tag, value; Serial.print("Enter tag: "); while (!Serial.available()) {} tag = Serial.readStringUntil('\n'); Serial.println(tag); tag.trim(); Serial.print("Enter value: "); while (!Serial.available()) {} value = Serial.readStringUntil('\n'); Serial.println(value); value.trim(); if (tag.length() > 0 && value.length() > 0) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=update&tag=" + tag + "&value=" + value; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); //Serial.println("Server response:"); //Serial.println(" "); while (client.connected()) { String line = client.readStringUntil('\n'); //Serial.println(line); if (line == "\r") { break; } } Serial.println("Update Done."); } } void getValue(){ String tag; Serial.print("Enter tag: "); while (!Serial.available()) {} tag = Serial.readStringUntil('\n'); Serial.println(tag); tag.trim(); if (tag.length() > 0) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=get&tag=" + tag; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.println("Get Result:"); for (JsonPair pair : obj) { String tag = pair.key().c_str(); //float value = pair.value().as(); String value = pair.value().as(); Serial.print("Tag: "); Serial.print(tag); Serial.print(" Content: "); Serial.println(value); } } } void deleteValue(){ String tag; Serial.print("Enter tag: "); while (!Serial.available()) {} tag = Serial.readStringUntil('\n'); Serial.println(tag); tag.trim(); if (tag.length()) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=delete&tag=" + tag; Serial.println("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); //Serial.println("Server response:"); //Serial.println(" "); while (client.connected()) { String line = client.readStringUntil('\n'); //Serial.println(line); if (line == "\r") { break; } } Serial.println("Delate Done."); } } void countValues(){ // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=count"; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.print("Count Result: "); for (JsonPair pair : obj) { String count = pair.key().c_str(); int value = pair.value().as(); //Serial.print("Count: "); //Serial.print(count); //Serial.print(" Value: "); Serial.println(value); } } void searchValues(){ String no, count; Serial.print("Search from NO: "); while (!Serial.available()) {} no = Serial.readStringUntil('\n'); Serial.println(no); no.trim(); Serial.print("Total count: "); while (!Serial.available()) {} count = Serial.readStringUntil('\n'); Serial.println(count); count.trim(); if (no.length() > 0 && count.length() > 0) { // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=search&no=" + no + "&count=" + count; Serial.print("Sending HTTP request to TinyWebDB: "); Serial.println(url); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.println("Search Result:"); for (JsonPair pair : obj) { String tag = pair.key().c_str(); //float value = pair.value().as(); String value = pair.value().as(); Serial.print("Tag: "); Serial.print(tag); Serial.print(" Content: "); Serial.println(value); } } } void showDB(){ // 发送POST请求 WiFiClient client; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/api?user=" + user + "&secret=" + secret + "&action=search&no=1&count=100"; //Serial.print("Sending HTTP request to TinyWebDB: "); //Serial.println(url); Serial.println("Searching..."); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // 等待服务器响应 while (!client.available()) { delay(1); } // 读取服务器响应 String response = ""; while (client.available()) { String line = client.readStringUntil('\r'); response += line; } //Serial.println(response); int start = response.indexOf("{"); int end = response.lastIndexOf("}") + 1; // Extract JSON data String json = response.substring(start, end); // 解析JSON数据 DynamicJsonDocument doc(1024); deserializeJson(doc, json); JsonObject obj = doc.as(); Serial.println("Search Result:"); for (JsonPair pair : obj) { String tag = pair.key().c_str(); //float value = pair.value().as(); String value = pair.value().as(); Serial.print("Tag: "); Serial.print(tag); Serial.print(" Content: "); Serial.println(value); } }

连续操作演示



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3