美文网首页熊爸的学习时间
玩转 ESP32 + Arduino (十四) HTTPCli

玩转 ESP32 + Arduino (十四) HTTPCli

作者: 熊爸天下_56c7 | 来源:发表于2020-09-10 00:09 被阅读0次

    我们使用ESP32_Arduino自带库: HTTPClient

    一. 请求相关API函数

    首先,创建一个客户端对象

    1. 初始化HTTP客户端 http_client.begin()

    /**
     * 解析url以获得所有参数,默认port是80端口
     * @param url String
     */
    bool begin(String url);
    
    /**
     * 解析url以获得所有参数,默认port是80端口
     * @param client : 传入一个网络连接客户端
     * @param url String
     */
    bool begin(WiFiClient &client, String url);
    
    /**
     * 设置host port 以及uri
     * @param host String(192.168.1.12,不需要带上http://前缀)
     * @param port uint16_t
     * @param uri  String
     */
    bool begin(String host, uint16_t port, String uri = "/");
    
    /**
     * 设置host port 以及uri
     * @param client 传入一个网络连接客户端
     * @param host String(192.168.1.12,不需要带上http://前缀)
     * @param port uint16_t
     * @param uri  String
     * @param https bool 是否启用https
     */
    bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false);
    
    /**
     * 设置host port 以及uri
     * @param host String(192.168.1.12,不需要带上http://前缀)
     * @param port uint16_t
     * @param uri  String
     * @param CAcert CA证书(https)
     */
    bool begin(String host, uint16_t port, String uri, const char* CAcert);
    bool begin(String host, uint16_t port, String uri, const char* CAcert, const char* cli_cert, const char* cli_key);
    

    2. 设置长连接 http_client.setReuse(true);

    /**
     * try to reuse the connection to the server
     * keep-alive 请求头
     * @param reuse bool
     */
    void setReuse(bool reuse); // keep-alive
    

    3. setUserAgent —— 封装标准请求头User-Agent

    /**
     * set User Agent
     * User Agent请求头:使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
     * @param userAgent const char *
     */
    void setUserAgent(const String& userAgent);
    

    4. addHeader —— 封装自定义请求头

    函数说明:

    /**
     * adds Header to the request
     * @param name  自定义请求头的名字
     * @param value 自定义请求头的参数值
     * @param first 是否要把当前请求头放在请求头的最前面
     * @param replace 是否需要替换之前已经存在该请求头的参数值,默认就是覆盖旧值
     */
    void addHeader(const String& name, const String& value, bool first = false, bool replace = true);
    

    5. GET 请求

    函数说明:

    /**
     * 发送一个get请求
     * @return http 状态码
     */
    int GET();
    

    6. POST 请求

    函数说明:

    /**
     * 发送一个post请求
     * @param payload uint8_t * 需要提交的数据
     * @param size size_t 提交的数据的字节数
     * @return http 状态码
     */
    int POST(uint8_t * payload, size_t size);
     
    /**
     * 发送一个post请求
     * @param payload String 需要提交的数据
     * @return http 状态码
     */
    int POST(String payload);
    

    7. PUT 请求

    函数说明:

    /**
     * 发送一个PUT请求(博主也没有用过PUT)
     * @param payload uint8_t * 需要提交的数据
     * @param size size_t 提交的数据的字节数
     * @return http 状态码
     */
    int PUT(uint8_t * payload, size_t size);
    /**
     * 发送一个PUT请求(博主也没有用过PUT)
     * @param payload String 需要提交的数据
     * @return http 状态码
     */
    int PUT(String payload);
    

    8. PATCH 请求

    函数说明:

    /**
     * 发送一个PATCH请求(博主也没有用过PATCH)
     * @param payload uint8_t * 需要提交的数据
     * @param size size_t 提交的数据的字节数
     * @return http 状态码
     */
    int PATCH(uint8_t * payload, size_t size);
    /**
     * 发送一个PATCH请求(博主也没有用过PATCH)
     * @param payload String 需要提交的数据
     * @return http 状态码
     */
    int PATCH(String payload);
    

    9. sendRequest 发送请求

    GET、POST、PUT、PATCH最终都会调用sendRequest方法。
    函数说明:

    /**
     * GET、POST、PUT、PATCH最终都会调用sendRequest方法
     * sendRequest
     * @param type const char * 请求类型    "GET", "POST", ....
     * @param payload String  请求携带的数据  data for the message body
     * @return
     */
    int sendRequest(const char * type, String payload);
    /**
     * sendRequest
     * @param type const char * 请求类型 "GET", "POST", ....
     * @param payload uint8_t * 请求携带的数据  data for the message body if null not send
     * @param size size_t  请求携带的数据字节数 size for the message body if 0 not send
     * @return -1 if no info or > 0 when Content-Length is set by server
     */
    int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0);
    /**
     * sendRequest
     * @param type const char *  请求类型 "GET", "POST", ....
     * @param stream Stream *  请求携带的数据流 data stream for the message body
     * @param size size_t   数据流大小 size for the message body if 0 not Content-Length is send
     * @return -1 if no info or > 0 when Content-Length is set by server
     */
    int sendRequest(const char * type, Stream * stream, size_t size = 0);
    

    10. setTimeout —— 设置请求超时

    函数说明:

    /**
     * 请求超时时间配置 ms为单位
     * @param timeout unsigned int  默认500ms
     */
    void setTimeout(uint16_t timeout);
    

    11. useHTTP10 —— http协议版本

    函数说明:

    /**
     * http协议版本
     * @param usehttp10 true表示用http1.0,默认是false,用http1.1
     */
    void useHTTP10(bool usehttp10 = true);
    

    12. end —— 结束请求

    函数说明:

    /**
     * 结束请求
     * called after the payload is handled
     */
    void end(void);
    

    二. 响应相关API

    1. collectHeaders —— 设置需要收集的响应头

    函数说明:

    /**
     * 设置需要收集的响应头(1-n个)
     * @param headerKeys[] const char *   响应头的名字
     * @param headerKeysCount const size_t 响应头的个数
     * 注意点:headerKeys数组元素个数需要大于等于 headerKeysCount
     */
    void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
    

    RequestArgument定义如下:

    struct RequestArgument {
        String key;//键值对里面的key
        String value;//键值对里面的value
    };
    

    注意点:

    这个方法收集的headerKeys会在响应数据处理函数中应用到;

    2. header(name) —— 获取具体响应头参数值

    函数说明:

    /**
     * 获取响应头参数值
     * @param name   const char *   响应头的名字
     * @return value of headerkey(name)
     */
    String header(const char* name);
    

    如果没有调用collectHeaders(),那就会默认返回空字符串;

    3. header(index) —— 获取第index个响应头参数值

    函数说明:

    /**
     * 获取第i个响应头参数值
     * @param i   size_t   响应头索引值
     * @return value of header index
     */
    String header(size_t i);
    

    如果没有调用collectHeaders(),那就会默认返回空字符串;

    4. headerName(index) —— 获取第i个响应头名字

    函数说明:

    /**
     * 获取第i个响应头名字
     * @param i   size_t   响应头索引值
     * @return name of header index
     */
    String headerName(size_t i);
    

    如果没有调用collectHeaders(),那就会默认返回空字符串;

    5. headers() —— 获取收集响应头个数

    函数说明:

    /**
     * 获取收集响应头个数
     * @return count int
     */
    int headers();                     // get header count
    

    6. hasHeader(name) —— 判断是否存在某一个响应头

    函数说明:

    /**
     * 判断是否存在某一个响应头
     * @param name   const char*   响应头名字
     * @return bool
     */
    bool hasHeader(const char* name);  // check if header exists
    

    7. handleHeaderResponse —— 处理响应头数据

    函数说明:

    /**
     * 读取从服务器返回的响应头数据
     * @return int http状态码
     */
    int handleHeaderResponse()
    

    8. getString —— 获取响应数据

    函数说明:

    /**
     * 把响应数据转成字符串 (可能需要很大内存空间)
     * @return String 响应数据转成字符串
     */
    String getString(void);
    

    9. getStream —— 获取响应数据的流

    函数说明:

    /**
     * 获取响应数据的流
     * @return WiFiClient& tcp响应数据的流
     */
    WiFiClient& getStream(void);
    

    10. getStreamPtr —— 获取响应数据的流

    函数说明:

    /**
     * 获取响应数据的流
     * @return WiFiClient& tcp响应数据的流
     */
    WiFiClient* getStreamPtr(void);
    

    11. writeToStream —— 获取响应数据的流,并写到其他流对象

    在讲解该函数之前,博主先给读者简单介绍一下 分块编码(Transfer-Encoding: chunked):

    Transfer-Encoding,是一个 HTTP 头部字段(响应头域),字面意思是「传输编码」。最新的 HTTP 规范里,只定义了一种编码传输:分块编码(chunked)。
    分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。
    数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。
    具体方法

    1. 在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。
    2. 每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。
    3. 最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
    /**
     * 把响应数据的流写到其他流对象
     * @param Stream* 其他流对象
     * @return int 写成功的字节数
     */
    int writeToStream(Stream* stream);
    

    12. getSize —— 获取响应数据的字节数

    函数说明:

    /**
     * 获取响应数据字节数
     * @return int 响应数据字节数
     */
    int getSize(void);
    

    13. errorToString —— 获取请求失败响应信息

    函数说明:

    /**
     * 根据错误码error返回具体错误信息
     * @param error 错误码
     * @return String 错误码对应的错误信息
     */
    static String errorToString(int error);
    
    #include <Arduino.h>
    #include "WiFi.h"
    #include "HTTPClient.h"
    
    const char *ssid = "anny";                      //wifi名
    const char *password = "20141208";              //wifi密码
    const char *host = "https://api.seniverse.com"; //心知天气APIhost
    const char *apiKey = "SZihSaRrzq6LclO30";       //API key 私钥
    const char *city = "taian";                     //查询的城市
    //示例: https://api.seniverse.com/v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c
    
    WiFiClient wifi_Client;
    HTTPClient http_client;
    String req;
    String rsp;
    
    class cityWeather
    {
    public:
      char cityName[16];
      char weather[32];
      char temp[16];
      char update[32];
    };
    
    //Wifi连接
    void setupWifi()
    {
      delay(10);
      Serial.println("connecting WIFI");
      WiFi.begin(ssid, password);
      while (!WiFi.isConnected())
      {
        Serial.print(".");
        delay(500);
      }
      Serial.println("OK");
      Serial.println("Wifi connected");
    }
    
    void setUpHttpClient()
    {
      req = (String)host + "/v3/weather/now.json?key=";
      req += apiKey;
      req += "&location=";
      req += city;
      req += "&language=zh-Hans&unit=c";
      Serial.println(req);
      if (http_client.begin(req))
      {
        Serial.println("HTTPclient setUp done!");
      }
    }
    
    void setup()
    {
      Serial.begin(115200);
      delay(3000);
      setupWifi();
      setUpHttpClient();
    }
    
    void loop()
    {
      int http_code = http_client.GET();
      Serial.println(http_code);
      if (http_code > 0)
      {
        Serial.printf("HTTP get code: %d\n", http_code);
        if (http_code == HTTP_CODE_OK)
        {
          rsp = http_client.getString();
          Serial.println(rsp);
        }
        else
        {
          Serial.printf("fail to get cityWeather,code:%d\n", http_code);
        }
      }
      delay(5000);
    }
    

    相关文章

      网友评论

        本文标题:玩转 ESP32 + Arduino (十四) HTTPCli

        本文链接:https://www.haomeiwen.com/subject/zmgjektx.html