Arduino网络编程实战-天气信息请求及数据解析

天气信息请求及数据解析

Arduino Ethernet Shield V1 允许 Arduino 板连接到互联网。 它基于 Wiznet W5100ethernet 芯片(数据表)。 Wiznet W5100 提供支持 TCP 和 UDP 的网络 (IP) 堆栈。 它最多支持四个同时套接字连接。

本实例将演示获取天气JSON数据及数据解析。

在这里插入图片描述

在前面的文章中,对JSON数据解析及HTTP请求已经做详细描述,请参考:

1、硬件准备

  • Arduino Mega 2560
  • Arduino Ethernet Shield
  • 路由器(推荐可以上网、开启DHCP)
  • 网线一条
  • 电脑一台

2、软件准备

本次使用的天气API服务为心知天气,请自行注册使用。

天气请求格式为:https://api.seniverse.com/v3/weather/now.json?key=私钥&location=beijing&language=zh-Hans&unit=c

请求返回天气信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"results": [
{
"location": {
"id": "C23NB62W20TF",
"name": "西雅图",
"country": "US",
"path": "西雅图,华盛顿州,美国",
"timezone": "America/Los\_Angeles",
"timezone\_offset": "-07:00"
},
"now": {
"text": "多云", //天气现象文字
"code": "4", //天气现象代码
"temperature": "14", //温度,单位为c摄氏度或f华氏度
"feels\_like": "14", //体感温度,单位为c摄氏度或f华氏度
"pressure": "1018", //气压,单位为mb百帕或in英寸
"humidity": "76", //相对湿度,0~100,单位为百分比
"visibility": "16.09", //能见度,单位为km公里或mi英里
"wind\_direction": "西北", //风向文字
"wind\_direction\_degree": "340", //风向角度,范围0~360,0为正北,90为正东,180为正南,270为正西
"wind\_speed": "8.05", //风速,单位为km/h公里每小时或mph英里每小时
"wind\_scale": "2", //风力等级,请参考:http://baike.baidu.com/view/465076.htm
"clouds": "90", //云量,单位%,范围0~100,天空被云覆盖的百分比 #目前不支持中国城市#
"dew\_point": "-12" //露点温度,请参考:http://baike.baidu.com/view/118348.htm #目前不支持中国城市#
},
"last\_update": "2015-09-25T22:45:00-07:00" //数据更新时间(该城市的本地时间)
}
]
}

在天气数据请求过程中,需要将Response的Header数据剔除,只保留返回的json数据

3、代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <ArduinoJson.h>
#include <Ethernet.h>
#include <SPI.h>

void setup() {
// Initialize Serial port
Serial.begin(9600);
while (!Serial) continue;

// Initialize Ethernet library
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
if (!Ethernet.begin(mac)) {
Serial.println(F("Failed to configure Ethernet"));
return;
}
delay(1000);

Serial.println(F("Connecting..."));

// Connect to HTTP server
EthernetClient client;
client.setTimeout(10000);
if (!client.connect("api.seniverse.com", 80)) {
Serial.println(F("Connection failed"));
return;
}

Serial.println(F("Connected!"));

// 构造HTTP请求头
client.println(F("GET /v3/weather/now.json?key=私钥&location=beijing&language=zh-Hans&unit=c HTTP/1.0"));
client.println(F("Host: api.seniverse.com"));
client.println("Content-Type: application/json");
client.println("Connection: close"); // or keep-live
client.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36");
client.println("Connection: close");
if (client.println() == 0) {
Serial.println(F("Failed to send request"));
client.stop();
return;
}

// 提取响应头
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
Serial.print(F("Unexpected response: "));
Serial.println(status);
client.stop();
return;
}

// 跳过响应头数据
char endOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
Serial.println(F("Invalid response"));
client.stop();
return;
}

// Allocate the JSON document
// Use arduinojson.org/v6/assistant to compute the capacity.
const size\_t capacity = 1024;
DynamicJsonDocument doc(capacity);

// 解析JSON数据
DeserializationError error = deserializeJson(doc, client);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f\_str());
client.stop();
return;
}
serializeJson(doc, Serial);
Serial.println();
// 提取天气数据
Serial.println(doc["results"][0]["location"]["id"].as<String>());
Serial.println(doc["results"][0]["location"]["name"].as<String>());
Serial.println(doc["results"][0]["location"]["country"].as<String>());
Serial.println(doc["results"][0]["location"]["path"].as<String>());
Serial.println(doc["results"][0]["location"]["timezone"].as<String>());
Serial.println(doc["results"][0]["location"]["timezone\_offset"].as<String>());
Serial.println(doc["results"][0]["now"]["text"].as<String>());
Serial.println(doc["results"][0]["now"]["code"].as<String>());
Serial.println(doc["results"][0]["now"]["temperature"].as<String>());
Serial.println(doc["results"][0]["last\_update"].as<String>());

// 关闭连接
client.stop();
}

void loop() {
// not used in this example
}

4、运行结果

在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/122921310