"); //-->
学习完ESP8266的网络相关操作后,就可以做个小实践来巩固所学的知识,同时对网络协议也会更加的理解。
获取天气信息采用的是心知天气提供的API接口,这也是目前比较受大家欢迎的一个平台。该实践的整个流程如下:
1. 进入心知天气官网注册账号,申请免费版本的数据API接口建立自己的项目之后获取秘钥。
2. 找到心知天气的接口文档,了解其请求地址,请求格式以及参数代表的含义,同时对其返回的数据格式进行分析。
3. 对接口了解之后下一步就要进行程序的设计,我们先来看一下实现的流程图,有了流程图之后我们思路就会变的清晰起来。
在向服务器发送数据请求时会用到HTTP的相关知识,在编程前我们先了解一下HTTP协议的相关知识。
HTTP协议又称为超文本传输协议(HyperText Transfer Protocol, HTTP)是分布式、协作式、超媒体系统应用之间的通信协议,是万维网(worldwideweb)交换信息的基础。它允许将超文本标记语言(HTML)文档从Web服务器传送到Web浏览器。HTML是一种用于创建文档的标记语言,这些文档包含相关信息的链接。可以通过单击一个链接来访问其他文档、图像或多媒体对象,并获得关于链接项的附加信息。
在制作Arduino网页服务器或者网页客户端时,需要理解HTTP协议的大原理。HTTP(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,绝大多数的Web开发都是构建在HTTP协议之上Web应用。
当使用浏览器(客户端)访问一个网页时,大致经过了以下三步:
①用户输人****后,浏览器(客户端)会向服务器发出HTTP请求;
②服务器收到请求后会返回HTML形式的文本以响应请求;
③浏览器收到服务器返回的HTML文本后,将文本转换为网页显示出来。
当客户端访问网页时,会先发起HTTP请求。HTTP请求由三部分组成,分别
是请求行、请求报头空行和请求数据,格式如下图所示:
服务器响应消息HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
在心知官方API文档中我们可知我们查询天气时需访问的接口为:请求方法为GET,所以我们在构造请求行是按上面的格式即可:
URL是:
/v3/weather/now.json?key=smtq3n0ixdggurox&location=beijing&language=zh-Hans&unit=c
协议版本为HTTP/1.1请求头部为:
Host:api.seniverse.com\r\n
Connection: keep-alive\r\n
我们只需要这几个,其他的网页和请求设备的描述我们不需要。
服务器返数据处理当向服务器仿宋数据请求后,服务器会发给我们发送返回的数据,我们需要按照服务器返回的格式解析出数据即可,心知天气返回的数据是JSON格式的,在解析JSON数据时arduino给我们提供了一个JSON解析工具使用起来很方便,可以直接生成代码****为:
,所以我们在网页上访问服务器把返回的JSON格式的数据放在解析工具上即可生成代码,在写程序时,直接把分离JSON格式的数据传进去即可。在使用这个工具时需要注意的是JSON版本号要和Arduino安装的JSON库的版本号是一致的,否则编译会出错。
完整代码如下:
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
WiFiClient client;
DynamicJsonBuffer jsonBuffer(800);
const char * ssid = "ChinaNet-fbMA";
const char * pwd = "qwertyuiop";
const char * host = "api.seniverse.com";
const int httpPort = 80;
bool bConnected = false;
struct WeatherData {
char city[16];//城市名称
char weather[32];//天气介绍(多云...)
char temp[16];//温度
char udate[32];//更新时间
};
WeatherData weatherData;
const char* json = "{\"results\":[{\"location\":{\"id\":\"WTW3SJ5ZBJUY\",\"name\":\"上海\",\"country\":\"CN\",\"path\":\"上海,上海,中国\",\"timezone\":\"Asia/Shanghai\",\"timezone_offset\":\"+08:00\"},\"daily\":[{\"date\":\"2019-02-11\",\"text_day\":\"多云\",\"code_day\":\"4\",\"text_night\":\"阴\",\"code_night\":\"9\",\"high\":\"7\",\"low\":\"2\",\"precip\":\"\",\"wind_direction\":\"东北\",\"wind_direction_degree\":\"45\",\"wind_speed\":\"10\",\"wind_scale\":\"2\"},{\"date\":\"2019-02-12\",\"text_day\":\"中雨\",\"code_day\":\"14\",\"text_night\":\"小雨\",\"code_night\":\"13\",\"high\":\"9\",\"low\":\"4\",\"precip\":\"\",\"wind_direction\":\"东\",\"wind_direction_degree\":\"90\",\"wind_speed\":\"10\",\"wind_scale\":\"2\"},{\"date\":\"2019-02-13\",\"text_day\":\"小雨\",\"code_day\":\"13\",\"text_night\":\"中雨\",\"code_night\":\"14\",\"high\":\"10\",\"low\":\"7\",\"precip\":\"\",\"wind_direction\":\"东北\",\"wind_direction_degree\":\"45\",\"wind_speed\":\"10\",\"wind_scale\":\"2\"}],\"last_update\":\"2019-02-11T08:00:00+08:00\"}]}";
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pwd);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// put your main code here, to run repeatedly:
String weather_data;
String line;
String url = "/v3/weather/daily.json?key=gske8kcghqz7cqiz&location=zhengzhou&language=zh-Hans&unit=c&start=0&days=3";
// if ( bConnected == false)
// {
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
delay(5000);
return;
}
bConnected = true;
Serial.println("connection ok");
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
Serial.print("向服务器发送的数据为:");
Serial.println(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
delay(100);
// }
while (client.available()) {
line = client.readStringUntil('\r');
weather_data += line;
}
Serial.println(weather_data);
String json_weather_data;
int jsonIndex;
for (int i = 0; i < weather_data.length(); i++) {
if (weather_data[i] == '{') {
jsonIndex = i;
break;
}
}
// Get JSON data
json_weather_data = weather_data.substring(jsonIndex);
Serial.println();
Serial.println("json_weather_data: ");
Serial.println(json_weather_data);
JsonObject& root = jsonBuffer.parseObject(json_weather_data);
if (!root.success())
{
Serial.println("parseObject() failed");
return;
}
else
{
Serial.println("开始解析数据");
JsonObject& results_0 = root["results"][0];
JsonObject& results_0_location = results_0["location"];
const char* results_0_location_name = results_0_location["name"]; // "上海"
const char* results_0_location_country = results_0_location["country"]; // "CN"
const char* upd = results_0["last_update"];
JsonArray& results_0_daily = results_0["daily"];
JsonObject& results_0_daily_0 = results_0_daily[0];
const char* results_0_daily_0_date = results_0_daily_0["date"];
const char*
results_0_daily_0_text_day = results_0_daily_0["text_day"]; // "多云"
const char*
results_0_daily_0_text_night = results_0_daily_0["text_night"]; // "阴
const char* results_0_daily_0_high = results_0_daily_0["high"]; // "7"
const char* results_0_daily_0_low = results_0_daily_0["low"]; // "2"
const char*
results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"]; // "东北"
Serial.println(results_0_location_name);
Serial.println(results_0_daily_0_date);
Serial.println(results_0_daily_0_text_day);
Serial.println(results_0_daily_0_text_night);
Serial.println(results_0_daily_0_high);
Serial.println(results_0_daily_0_low);
Serial.println(results_0_daily_0_wind_direction);
Serial.println(upd);
}
client.stop();
weather_data="";
Serial.println("closing connection");
delay(10000);
}
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。