ESP32上手笔记 | 03 -通过HTTP获取天气信息(WiFi+HTTPClient+ArduinoJson)

Posted Mculover666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ESP32上手笔记 | 03 -通过HTTP获取天气信息(WiFi+HTTPClient+ArduinoJson)相关的知识,希望对你有一定的参考价值。

一、WIFI库

使用时包含头文件:

#include <WiFi.h>

1. 连接WiFi

/**
 * Start Wifi connection
 * if passphrase is set the most secure supported mode will be automatically selected
 * @param ssid const char*          Pointer to the SSID string.
 * @param passphrase const char *   Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
 * @param bssid uint8_t[6]          Optional. BSSID / MAC of AP
 * @param channel                   Optional. Channel of AP
 * @param connect                   Optional. call connect
 * @return
 */
wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect);

2. 检查WiFi连接状态

/**
 * Return Connection status.
 * @return one of the value defined in wl_status_t
 *
 */
wl_status_t WiFiSTAClass::status();

返回值wl_status_t的枚举如下:

typedef enum 
    WL_NO_SHIELD        = 255,   // for compatibility with WiFi Shield library
    WL_IDLE_STATUS      = 0,
    WL_NO_SSID_AVAIL    = 1,
    WL_SCAN_COMPLETED   = 2,
    WL_CONNECTED        = 3,
    WL_CONNECT_FAILED   = 4,
    WL_CONNECTION_LOST  = 5,
    WL_DISCONNECTED     = 6
 wl_status_t;

3. 断开WiFi连接

/**
 * Disconnect from the network
 * @param wifioff
 * @return  one value of wl_status_t enum
 */
bool WiFiSTAClass::disconnect(bool wifioff, bool eraseap);

4. 设置WiFi模式

/**
 * set new mode
 * @param m WiFiMode_t
 */
bool WiFiGenericClass::mode(wifi_mode_t m);

WiFi模式wifi_mode_t的枚举如下:

typedef enum 
    WIFI_MODE_NULL = 0,  /**< null mode */
    WIFI_MODE_STA,       /**< WiFi station mode */
    WIFI_MODE_AP,        /**< WiFi soft-AP mode */
    WIFI_MODE_APSTA,     /**< WiFi station + soft-AP mode */
    WIFI_MODE_MAX
 wifi_mode_t;

为了方便使用,又封装了一些宏:

#define WIFI_OFF     WIFI_MODE_NULL
#define WIFI_STA     WIFI_MODE_STA
#define WIFI_AP      WIFI_MODE_AP
#define WIFI_AP_STA  WIFI_MODE_APSTA

5. 查看本地ip

/**
 * Get the station interface IP address.
 * @return IPAddress station IP
 */
IPAddress WiFiSTAClass::localIP()

获取到的IPAddress是一个类,可以调用其 tostring() 方法转换为字符串。

demo

#include <Arduino.h>
#include <WiFi.h>

const char *ssid = "Mculover666";
const char *pwd  = "mculover666";

void setup() 
    Serial.begin(115200);

    //connect to WiFi
    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, pwd);
    while (WiFi.status() != WL_CONNECTED) 
        Serial.print(".");
        delay(500);
    
    Serial.println("Connected!");

    // local ip
    Serial.println(WiFi.localIP().toString());

    // WiFi disconnect
    WiFi.disconnect();
    Serial.println("WiFi Disconnected!");

    // WiFi Close
    WiFi.mode(WIFI_OFF);
    Serial.println("WiFi is off!");


void loop() 
    delay(1000);

二、HTTPClient库

使用时包含头文件:

#include <HTTPClient.h>

1. 创建对象

HTTPClient http;

2. HTTPClient对象初始化

/*
 * Since both begin() functions take a reference to client as a parameter, you need to 
 * ensure the client object lives the entire time of the HTTPClient
 */
    bool begin(WiFiClient &client, String url);
    bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false);

#ifdef HTTPCLIENT_1_1_COMPATIBLE
    bool begin(String url);
    bool begin(String url, const char* CAcert);
    bool begin(String host, uint16_t port, String uri = "/");
    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);
#endif

3. 发起HTTP请求

/// request handling
int GET();
int PATCH(uint8_t * payload, size_t size);
int PATCH(String payload);
int POST(uint8_t * payload, size_t size);
int POST(String payload);
int PUT(uint8_t * payload, size_t size);
int PUT(String payload);

4. 获取http响应内容

/**
 * return all payload as String (may need lot of ram or trigger out of memory!)
 * @return String
 */
String HTTPClient::getString(void);

5. 关闭http

/**
 * end
 * called after the payload is handled
 */
void HTTPClient::end(void);

demo

获取b站粉丝数的API非常简单,vmid是用户id:

http://api.bilibili.com/x/relation/stat?vmid=314597633

返回一行json数据:

"code":0,"message":"0","ttl":1,"data":"mid":314597633,"following":303,"whisper":0,"black":0,"follower":237

测试代码如下:

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char *ssid = "Mculover666";
const char *pwd  = "mculover666";

void setup() 
    Serial.begin(115200);

    //connect to WiFi
    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, pwd);
    while (WiFi.status() != WL_CONNECTED) 
        Serial.print(".");
        delay(500);
    
    Serial.println("Connected!");

    // local ip
    Serial.println(WiFi.localIP().toString());

    // HTTPClient init
    HTTPClient http;
    String url = "http://api.bilibili.com/x/relation/stat?vmid=314597633";
    http.begin(url);

    // start get
    int http_code = http.GET();

    // handle http code
    if (http_code !=  HTTP_CODE_OK) 
        // get fail.
        Serial.printf("GET fail, http code is %s\\n", http.errorToString(http_code).c_str());
        return;
    

    // http response
    String response = http.getString();
    Serial.printf("response:[%s]\\n", response.c_str());

    // extract follower
    int pos = response.indexOf("follower");
    String follower_str = response.substring(pos + 10, response.length() - 2);
    int follower = atoi(follower_str.c_str());
    Serial.printf("your follower:%d\\n", follower);

    // close http
    http.end();


void loop() 
    delay(1000);

三、ArduinoJson库

当API返回的json复杂起来时,需要使用json库进行解析,arduino上比较好用的是arduinojson

1. 安装

git clone https://github.com/bblanchon/ArduinoJson.git

将下载的文件夹放到platformio工程的lib目录下:

2. 使用方法

头文件:

#include <ArduinoJson.h>

参考:玩转 ESP32 + Arduino (十五) ArduinoJSON库(V6版本)

四、获取天气

1. API

获取的天气我使用心知天气,有免费版API可用。

接口API为:

https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c

https://api.seniverse.com/v3/weather/now.json?key=Sed_lnwUBFUn2yVth&location=shenzhen&language=zh-Hans&unit=c

返回结果示例:


	"results":
	[
		"location":
		
			"id":"WS10730EM8EV",
			"name":"深圳",
			"country":"CN",
			"path":"深圳,深圳,广东,中国",
			"timezone":"Asia/Shanghai",
			"timezone_offset":"+08:00"
		,
		"now":
		
			"text":"阴",
			"code":"9",
			"temperature":"23"
		,
		"last_update":"2022-03-15T19:23:46+08:00"
	]

2. demo

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char *ssid = "Mculover666";
const char *pwd  = "mculover666";
const String xz_api_key = "your api key";
const String city = "shenzhen";
DynamicJsonDocument doc(1024);

/***************************************************

	"results":
	[
		"location":
		
			"id":"WS10730EM8EV",
			"name":"深圳",
			"country":"CN",
			"path":"深圳,深圳,广东,中国",
			"timezone":"Asia/Shanghai",
			"timezone_offset":"+08:00"
		,
		"now":
		
			"text":"阴",
			"code":"9",
			"temperature":"23"
		,
		"last_update":"2022-03-15T19:23:46+08:00"
	]

*****************************************************/

void setup() 
    Serial.begin(115200);

    //connect to WiFi
    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, pwd);
    while (WiFi.status() != WL_CONNECTED) 
        Serial.print(".");
        delay(500);
    
    Serial.println("Connected!");

    // local ip
    Serial.println(WiFi.localIP().toString());


int get_weather(void)

    HTTPClient http;
    String url = "https://api.seniverse.com/v3/weather/now.json?key=" + xz_api_key + "&location=" + city + "&language=zh-Hans&unit=c";

    // HTTPClient init
    http.begin(url);

    // start get
    int http_code = http.GET();

    // handle http code
    if (http_code !=  HTTP_CODE_OK) 
        // get fail.
        Serial.printf("GET fail, http code is %s\\n", http.errorToString(http_code).c_str());
        return -1;
    

    // http response
    String response = http.getString();
    Serial.printf("response:[%s]\\n", response.c_str());

    // extract weather
    deserializeJson(doc, response);
    JsonObject root = doc.as<JsonObject>();
    JsonArray results = root["results"];
    // location
    JsonObject location = results[0]["location"];
    const char *path = location["path"];
    Serial.println(path);
    // now
    JsonObject now = results[0]["now"];
    const char *text = now["text"];
    const char *temperature = now["temperature"];
    Serial.println(text);
    Serial.println(temperature);
    // last_update
    const char *last_update = results[0]["last_update"];
    Serial.println(last_update);

    // close http
    http.end();

    return 0;



void loop() 
    get_weather();
    delay(60000);

以上是关于ESP32上手笔记 | 03 -通过HTTP获取天气信息(WiFi+HTTPClient+ArduinoJson)的主要内容,如果未能解决你的问题,请参考以下文章

ESP32-C3上手笔记 | 01 - ESP32 C3开发环境搭建(ESP-IDF)

ESP32上手笔记 | 06 -驱动1.3‘ ST7789 SPI屏幕(TFT_eSPI)

ESP32 单片机学习笔记 - 03 - MCPWM脉冲输出/PCNT脉冲计数

esp32开发板上手micropython--windows环境

ESP32 MicroPython开发之旅 设备篇⑦ —— dht11 OLED ssd1306,简单上手

开源智能手表TTGO-WATCH上手把玩环境配置