NodeMCU获取并解析心知天气信息

1 注册心知天气并获取私钥

打开心知天气网站,点击注册按钮

填写基本信息注册心知天气账号,登录注册所填写的邮箱点击链接进行账号激活,随后出现如下界面

点击登录按钮进行登录之后来到以下界面

注册登录之后账户下是默认没有API产品的,需要申请免费版天气数据API

免费版申请成功之后,即可在用户控制台界面看到所申请的免费版API产品了,在以下界面获取私钥信息并保存,我们接下来对API发起请求时需要使用到私钥

至此,就已经完成了心知天气的注册和密钥获取,需要说明的是免费版API产品只包含以下几个API获取权限,并且访问频率限制(20次/分钟),以下是几个产品的文档介绍

1.1 免费用户可以获取的API信息

您也可以在浏览器输入以下API并回车查看服务器返回的Json格式的天气信息数据

(使用从心知天气控制台获取的私钥进行替换以下的"xxxxxxxxxxxxxxxxx")

天气实况

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

生活指数

https://api.seniverse.com/v3/life/suggestion.json?key=xxxxxxxxxxxxxxxxx&location=shanghai&language=zh-Hans

三天天气预报

https://api.thinkpage.cn/v3/weather/daily.json?key=xxxxxxxxxxxxxxxxx&location=beijing&language=zh-Hans&unit=c&start=0&days=3

2 使用ArduinoJson解析天气信息

接下来我们会使用NodeMCU对以上申请的API发起请求,服务器响应并返回天气信息的Json数据,对接收到的Json数据使用ArduinoJson库进行解析,期间会用到的工具是ArduinoJson提供的在线解析工具

示例程序将以获取当前IP地区的天气实况API为例,解析服务器返回的数据并将其打印到串口

https://api.seniverse.com/v3/weather/now.json?key=SZxTn61CIIDoyc1AI&location=ip&language=zh-Hans&unit=c
示例程序
/**
Get the Weather from intenet with esp8266 get data from 心知天气:[url=http://www.thinkpage.cn/]http://www.thinkpage.cn/[/url]
api 文档说明:[url=http://www.thinkpage.cn/doc]http://www.thinkpage.cn/doc[/url]
city id list download :[url=http://www.thinkpage.cn/data/thinkpage_cities.zip]http://www.thinkpage.cn/data/thinkpage_cities.zip[/url] Created by yfrobot, 2016.8.23
This example is in public domain.
*/ #include <ESP8266WiFi.h>
#include <ArduinoJson.h> WiFiClient client; const char* ssid = "YFROBOT"; // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* password = "yfrobot2016"; // XXXXXX -- 使用时请修改为当前你的 wifi 密码 const char* host = "api.thinkpage.cn";
const char* APIKEY = "24qbvr1mjsnukavo"; //API KEY
const char* city = "huaian";
const char* language = "en";
//心知天气获取连接:[url=https://api.thinkpage.cn/v3/weather/daily.json?key=KEY&location=]https://api.thinkpage.cn/v3/weather/daily.json?key=KEY&location=[/url]城市&language=zh-Hans&unit=c&start=-1&days=5 const unsigned long BAUD_RATE = 115200; // serial connection speed
const unsigned long HTTP_TIMEOUT = 2100; // max respone time from server
const size_t MAX_CONTENT_SIZE = 2048; // max size of the HTTP response // Skip HTTP headers so that we are at the beginning of the response's body
// -- 跳过 HTTP 头,使我们在响应正文的开头
bool skipResponseHeaders() {
// HTTP headers end with an empty line
char endOfHeaders[] = "\r\n\r\n"; client.setTimeout(HTTP_TIMEOUT);
bool ok = client.find(endOfHeaders); if (!ok) {
Serial.println("No response or invalid response!");
} return ok;
} // 发送请求指令
bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
// We now create a URI for the request
//心知天气
String GetUrl = "/v3/weather/now.json?key=";
GetUrl += apiKey;
GetUrl += "&location=";
GetUrl += city;
GetUrl += "&language=";
GetUrl += language; // This will send the request to the server
client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
return true;
} // Read the body of the response from the HTTP server -- 从HTTP服务器响应中读取正文
void readReponseContent(char* content, size_t maxSize) {
size_t length = client.peekBytes(content, maxSize);
delay(100);
Serial.println("Get the data from Internet!");
content[length] = 0;
Serial.println(content);
Serial.println("Read Over!");
} // The type of data that we want to extract from the page -- 我们要从此网页中提取的数据的类型
struct UserData {
char city[16];
char cnty[16];
char weather[32];
char temp[16];
char feel[16];
char hum[16];
char visi[16];
char udate[32];
}; // 解析数据
bool parseUserData(char* content, struct UserData* userData) {
// Compute optimal size of the JSON buffer according to what we need to parse.
// -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
// This is only required if you use StaticJsonBuffer. -- 如果你使用StaticJsonBuffer时才需要
// const size_t BUFFER_SIZE = 1024; // Allocate a temporary memory pool on the stack -- 在堆栈上分配一个临时内存池
// StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
// -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
// If the memory pool is too big for the stack, use this instead:
DynamicJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(content); if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
// const char* x = root["results"][0]["location"]["name"];//
// Serial.println(x);
// Here were copy the strings we're interested in -- 复制我们感兴趣的字符串
strcpy(userData->city, root["results"][0]["location"]["name"]);
strcpy(userData->cnty, root["results"][0]["location"]["country"]);
strcpy(userData->weather, root["results"][0]["now"]["text"]);
strcpy(userData->temp, root["results"][0]["now"]["temperature"]);
strcpy(userData->feel, root["results"][0]["now"]["feels_like"]);
strcpy(userData->hum, root["results"][0]["now"]["humidity"]);
strcpy(userData->visi, root["results"][0]["now"]["visibility"]);
strcpy(userData->udate, root["results"][0]["last_update"]);
// It's not mandatory to make a copy, you could just use the pointers
// Since, they are pointing inside the "content" buffer, so you need to make
// sure it's still in memory when you read the string
// -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
// 当你读取字符串时它仍在内存中 return true;
} // Print the data extracted from the JSON -- 打印从JSON中提取的数据
void printUserData(const struct UserData* userData) {
Serial.println("Print parsed data :");
Serial.print("City : ");
Serial.print(userData->city);
Serial.print(", \t");
Serial.print("Country : ");
Serial.println(userData->cnty); Serial.print("Weather : ");
Serial.print(userData->weather);
Serial.print(",\t");
Serial.print("Temp : ");
Serial.print(userData->temp);
Serial.print(" C");
Serial.print(",\t");
Serial.print("Feel : ");
Serial.print(userData->feel);
Serial.print(" C");
Serial.print(",\t");
Serial.print("Humidity : ");
Serial.print(userData->hum);
Serial.print(" %");
Serial.print(",\t");
Serial.print("visibility : ");
Serial.print(userData->visi);
Serial.println(" km"); Serial.print("Last Updata : ");
Serial.print(userData->udate);
Serial.println("");
} // Close the connection with the HTTP server -- 关闭与HTTP服务器连接
void stopConnect() {
Serial.println("Disconnect");
client.stop();
} void setup(){
WiFi.mode(WIFI_STA); //设置esp8266 工作模式 Serial.begin(BAUD_RATE ); //设置波特率
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid); WiFi.begin(ssid, password); //连接wifi
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
delay(500);
// Check if a client has connected
if (!client.connect(host, 80)) {
Serial.println("connection failed");
return;
} if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
char response[MAX_CONTENT_SIZE];
readReponseContent(response, sizeof(response));
UserData userData;
if (parseUserData(response, &userData)) {
printUserData(&userData);
}
}
stopConnect();
}
void loop(){
delay(3000);
} /*
心知天气参数 location
所查询的位置
参数值范围:
城市拼音/英文名 例如:location=beijing
城市中文名 例如:location=北京 (ESP8266不支持中文)
城市ID 例如:location=WX4FBXXFKE4F
经纬度 例如:location=39.93:116.40 (注意纬度前经度在后,冒号分隔)
IP地址 例如:location=220.181.111.86
“ip”两个字母 自动识别请求IP地址,例如:location=ip language
语言 (可选)
参数值范围:
en 英文
zh-Hans 简体中文
zh-Hant 繁体中文
ja 日语
de 德语
fr 法语
hi 印地语(印度官方语言之一)
id 印度尼西亚语
ru 俄语
th 泰语
默认值:zh-Hans unit
单位 (可选)
参数值范围:
c 当参数为c时,温度c、风速km/h、能见度km、气压mb
f 当参数为f时,温度f、风速mph、能见度mile、气压inch
默认值:c 天气代码
代码 中文 英文 图标
0 晴 Sunny 晴
1 晴 Clear 晴
2 晴 Fair 晴
3 晴 Fair 晴
4 多云 Cloudy 多云
5 晴间多云 Partly Cloudy 晴间多云
6 晴间多云 Partly Cloudy 晴间多云
7 大部多云 Mostly Cloudy 大部多云
8 大部多云 Mostly Cloudy 大部多云
9 阴 Overcast 阴
10 阵雨 Shower 阵雨
11 雷阵雨 Thundershower 雷阵雨
12 雷阵雨伴有冰雹 Thundershower with Hail 雷阵雨伴有冰雹
13 小雨 Light Rain 小雨
14 中雨 Moderate Rain 中雨
15 大雨 Heavy Rain 大雨
16 暴雨 Storm 暴雨
17 大暴雨 Heavy Storm 大暴雨
18 特大暴雨 Severe Storm 特大暴雨
19 冻雨 Ice Rain 冻雨
20 雨夹雪 Sleet 雨夹雪
21 阵雪 Snow Flurry 阵雪
22 小雪 Light Snow 小雪
23 中雪 Moderate Snow 中雪
24 大雪 Heavy Snow 大雪
25 暴雪 Snowstorm 暴雪
26 浮尘 Dust 浮尘
27 扬沙 Sand 扬沙
28 沙尘暴 Duststorm 沙尘暴
29 强沙尘暴 Sandstorm 强沙尘暴
30 雾 Foggy 雾
31 霾 Haze 霾
32 风 Windy 风
33 大风 Blustery 大风
34 飓风 Hurricane 飓风
35 热带风暴 Tropical Storm 热带风暴
36 龙卷风 Tornado 龙卷风
37 冷 Cold 冷
38 热 Hot 热
99 未知 Unknown 常用心知天气API
英文天气实况:
https://api.thinkpage.cn/v3/weather/now.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=en&unit=c 中文天气实况:
https://api.thinkpage.cn/v3/weather/now.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=zh-Hans&unit=c 天气预报
三日中文天气预报:
https://api.thinkpage.cn/v3/weather/daily.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=zh-Hans&unit=c&start=0&days=3 三天英文天气预报:
https://api.thinkpage.cn/v3/weather/daily.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=en&unit=c&start=0&days=3 https://api.thinkpage.cn/v3/weather/daily.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=en&unit=c&start=1&days=1 中文生活指数:
https://api.thinkpage.cn/v3/life/suggestion.json?key=xxxxxxxxxxxxxxxx&location=beijing&language=zh-Hans 注意:使用时请将以上信息的xxxxxxxxxxxxxxxx更换为自己的心知天气认证密钥码 */

NodeMCU获取并解析心知天气信息的更多相关文章

  1. 心知天气数据API 产品的高并发实践

    心知天气数据API 产品的高并发实践 心知天气作为国内领先的商业气象服务提供商,天气数据API 产品从公司创立以来就一直扮演着很重要的角色.2009 年API 产品初次上线,历经十年,我们不断用心迭代 ...

  2. ESP32 IDF 获取天气信息

    一.注册天气获取账号 我使用的知心天气,没有获取天气账号的小伙伴可以去注册一下,知心天气官网:https://www.seniverse.com/ 取得天气获取的API后,可以直接在浏览器中访问测试一 ...

  3. PyQuery爬取历史天气信息

    1.准备工作: 网址:https://lishi.tianqi.com/xian/index.html 爬虫类库:PyQuery,requests 2.网页分析: 红线部分可更改为需要爬取的城市名,如 ...

  4. java解析xml实例——获取天气信息

    获取xml并解析其中的数据: package getweather.xml; import java.io.IOException; import java.util.HashMap; import ...

  5. 半吊子学习Swift--天气预报程序-获取天气信息

    昨天申请的彩云天气Api开发者今天上午已审核通过  饭后运动过后就马不停蹄的来测试接口,接口是采用经纬度的方式来获取天气信息,接口地址如下 https://api.caiyunapp.com/v2/ ...

  6. Java通过webservice接口获取天气信息

    通过SOAP请求的方式获取天气信息并解析返回的XML文件. 参考: http://www.webxml.com.cn/WebServices/WeatherWS.asmx import java.io ...

  7. 用百度SDK获取地理位置和天气信息

    以下实现通过百度SDK获取地理位置和天气信息,请參考title=android-locsdk/guide/v5-0">百度开发文档 1. 在相关下载最新的库文件.将so文件的压缩文件解 ...

  8. Android实现自动定位城市并获取天气信息

    定位实现代码: <span style="font-size:14px;">import java.io.IOException; import java.util.L ...

  9. Linux网络编程之"获取网络天气信息"

    需求分析: 1.需要Linux c 网络编程基础, 2.需要了解 http 协议 3.需要天气信息相关api(可以从阿里云上购买,很便宜的!) 4.需要cJSON解析库(因为获取到的天气信息一般是用c ...

随机推荐

  1. python常用操作和内置函数

    一.常用数据处理方法. 1.索引:按照号码将对应位置的数据取出使用 2.list将任意类型数据用逗号分割存在列表中 3.range:产生一堆数字(顾头不顾尾) 4.切片:可以从复制数据的一部分,不影响 ...

  2. introJs用法及在webkit内核浏览器的一个报错

    1.用法 很简单的用法,引入js,引入css,再执行introJs().start();就可以了(备注:introJs会自动去抓取含有data-intro的dom在introJs源码中_introFo ...

  3. 串的模式匹配算法1 BF算法

    BF算法 字符串的模式匹配不一定要从主串的第一个位置开始,可以指定主串中查找的起始位置 pos. 2. 算法步骤: 1)分别利用计数器指针 i 和 j 指定主串和模式串即小字符串待比较的位置,初始化为 ...

  4. Android事件分发机制一:事件是如何到达activity的?

    事件分发,真的一定从Activity开始吗? 前言 很高兴遇见你~ 事件分发,android中一个老生常谈的话题了.基本的流程我们也都知道是从Activity开始分发,但有一个关键问题是:事件是如何到 ...

  5. wpf 通过为DataGrid所绑定的数据源类型的属性设置Attribute改变DataGrid自动生成列的顺序

    环境Win10 VS2019 .Net Framework4.8 在wpf中,如果为一个DataGrid绑定到一个数据源,默认情况下DataGrid会为数据源类型的每个属性生成一个列(Column)对 ...

  6. 【Spring】 Spring的核心容器

    Spring的核心容器 文章目录 Spring的核心容器 BeanFactory ApplicationContext 1.通过ClassPathXmlApplicationContext创建 2.通 ...

  7. 【Git】Git初始化一个仓库

    文章目录 初始化仓库 检查当前文件状态 跟踪新文件 提交更新 跳过使用暂存区域 移除文件 添加远程仓库 推送到远程仓库 简单记录-慕课网 从0开始 独立完成企业级Java电商网站开发 Git初始化一个 ...

  8. postman接口测试之复制多个接口或collections到某个子文件夹或collections下

    一.痛点 1.postman只支持复制一个请求,或者一个子文件夹,但是不支持复制多个请求,或者整个collections到某个子文件夹或者某个collections下. 2.网上查了好一会儿,没有一个 ...

  9. Gulp4.0入门和实战

    gulp4.0入门和实战 我最近遇到需要优化web的性能的任务,然后就捣鼓了一些对资源文件优化压缩的方案.由于之前的项目中有使用到gulp,所以在需要处理的web项目中也优先使用这个技术. 先聊聊gu ...

  10. linux下删除文件夹及下面所有文件

    使用rm -rf 目录名字 命令即可 -r 就是向下递归,不管有多少级目录,一并删除-f 就是直接强行删除,不作任何提示的意思 rm 不带参数 只能删除文件 rm test.txt mkdir /us ...