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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mculover666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值