在分析代码之前,首先介绍 ArduinoJson 库的安装及“心知天气”的ID申请

一、安装 ArduinoJson 库

  进入 Arduino 开发环境后,选择菜单栏-->工具-->管理库,搜索“arduinojson”。尽量使用 ArduinoJson 5.x 版本,因为 6.x 版本有很大的改动。

二、申请“心知天气”的个人APIKEY

  首先进入“心知天气”主页,点击此处访问

  注册并登陆后,点击“立即免费试用”

  申请免费版

  获取自己的API密钥

三、“心知天气”API简介

  本部分内容参考自:https://www.jianshu.com/p/fd8c84e40994

  1. API 请求参数

参数名 参数类型 参数意义 是否必选
key string 个人API密钥 true
location string 查询的地理位置 true
language string 结果表示的语言 false,默认简体中文
unit string 结果表示的单位 false,默认摄氏度

  本实验中,language 的参数值选用“zh-Hans”简体中文,unit 的参数选用“c”。(想了解更多参数范围请看参考链接)

  2. API 响应参数

参数名 参数类型
location 对象:包括 id, name, country, path, timezone, timezone_offset
now 对象:包括 text, code, temperature
last_update 日期

  参考一个请求的 Json 数据的实例,应该能较直观地理解 Json 数据包的格式:

{
  "results":[
    {
      "location":{
        "id":"WTMKQ069CCJ7",
        "name":"杭州",
        "country":"CN",
        "path":"杭州,杭州,浙江,中国",
        "timezone":"Asia/Shanghai",
        "timezone_offset":"+08:00"
      },
      "now":{
        "text":"晴",
        "code":"1",
        "temperature":"18"
      },
      "last_update":"2020-11-07T21:25:00+08:00"
    }
  ]
}

  引用数据时,用类似数组的引用方式。

  例如,若想引用地区名 “杭州”,则使用:

json["results"][0]["location"]["name"]

四、代码分析

  本次实验代码已上传至本人 github 账号:点击此处查看完整代码

  1.变量设置

#include<ESP8266WiFi.h>
#include<ArduinoJson.h> const char* ssid ="";//输入热点名称
const char* password ="";//输入热点密码
const char* host ="api.seniverse.com";
const char* APIKEY ="";//输入自己申请的知心天气私钥
const char* city ="hangzhou";//可根据需要改为其余城市的拼音
const char* language ="zh-Hans"; const unsigned long BAUD_RATE=115200;
const unsigned long HTTP_TIMEOUT=5000;
const size_t MAX_CONTENT_SIZE=1000; struct WeatherData{//存储天气数据的结构体,可根据需要自行添加成员变量
char city[16];
char weather[32];
char temp[16];
char udate[32];
}; WiFiClient client;//创建了一个网络对象
char response[MAX_CONTENT_SIZE];
char endOfHeaders[]="\r\n\r\n";

  2.初始化

  在这一步中 设置串口的波特率,连接WiFi,设置客户端超时时间

void setup() {
Serial.begin(BAUD_RATE);
wifiConnect();//连接WiFi
client.setTimeout(HTTP_TIMEOUT);
}

  3.循环体

  首先判断 tcp client 是否处于连接状态,若不是,则尝试建立连接。连接成功后,发送 http 请求,并且跳过响应头,直接获取响应 body。

void loop() {
while(!client.connected()){
if(!client.connect(host,80)){//尝试建立连接
Serial.println("connection....");
delay(500);
}
}
//连接成功,发送GET请求
if(sendRequest(host,city,APIKEY)&&skipResponseHeaders()){//发送http请求 并且跳过响应头
clrEsp8266ResponseBuffer();//清除缓存
readReponseContent(response,sizeof(response));//从HTTP服务器响应中读取正文
WeatherData weatherData;
if(parseUserData(response,&weatherData)){//判断Json数据包是否分析成功
printUserData(&weatherData);//输出读取到的天气信息
}
}
 stopConnect();
delay(5000);
}

  4.自定义函数详解

    (1) 连接到WiFi

void wifiConnect(){
WiFi.mode(WIFI_STA);//设置esp8266工作模式
Serial.print("Connecting to");
Serial.println(ssid);
WiFi.begin(ssid,password);//连接WiFi
WiFi.setAutoConnect(true);
while(WiFi.status()!=WL_CONNECTED){//该函数返回WiFi的连接状态
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
delay(500);
Serial.println("IP address:");
Serial.println(WiFi.localIP());
}

    (2) 发送 http 请求

bool sendRequest(const char* host,const char* cityid,const char* apiKey){
String GetUrl="/v3/weather/now.json?key=";
GetUrl+=APIKEY;
GetUrl+="&location=";
GetUrl+=city;
GetUrl+="&language=";
GetUrl+=language;
GetUrl+="&unit=c ";
client.print(String("GET ")+GetUrl+"HTTP/1.1\r\n"+"Host:"+host+"\r\n"+"Connection:close\r\n\r\n");
Serial.println("creat a request:");
Serial.println(String("GET ")+GetUrl+"HTTP/1.1\r\n"+"Host:"+host+"\r\n"+"Connection:close\r\n\r\n");
delay(1000);
return true;
}

    (3) 跳过响应头

bool skipResponseHeaders(){
bool ok=client.find(endOfHeaders);
if(!ok){
Serial.println("No response of invalid response!");
}
return ok;
}

    (4) 读取响应的正文信息

void readReponseContent(char* content,size_t maxSize){
size_t length=client.readBytes(content,maxSize);
delay(100);
Serial.println("Get the data from Internet");
content[length]=0;
Serial.println(content);//输出读取到的数据
Serial.println("Read data Over!");
client.flush();//刷新客户端
}

    (5) 分析 Json 数据包

bool parseUserData(char* content,struct WeatherData* weatherData){
DynamicJsonBuffer jsonBuffer;//创建一个动态缓冲区实例
JsonObject&root=jsonBuffer.parseObject(content);//根据需要解析的数据来计算缓冲区的大小
if(!root.success()){
Serial.println("JSON parsing failed!");
return false;
}
//复制数据包中所需的字符串
strcpy(weatherData->city,root["results"][0]["location"]["name"]);
strcpy(weatherData->weather,root["results"][0]["now"]["text"]);
strcpy(weatherData->temp,root["results"][0]["now"]["temperature"]);
strcpy(weatherData->udate,root["results"][0]["last_update"]); return true;
}

    (6) 打印数据

void printUserData(const struct WeatherData* weatherData){
Serial.println("Print parsed data:");
Serial.print("City:");
Serial.print(weatherData->city);
Serial.print(" Weather:");
Serial.print(weatherData->weather);
Serial.print(" Temp:");
Serial.print(weatherData->temp);
Serial.print("℃");
Serial.print(" UpdateTime:");
Serial.println(weatherData->udate);
}

    (7) 停止客户端访问

void stopConnect(){
Serial.println("Disconnect");
client.stop();//停止客户端访问
}

    (8) 清除缓存

void clrEsp8266ResponseBuffer(void){
memset(response,0,MAX_CONTENT_SIZE);
}

五、串口输出样例

六、总结

  在本次实践中,我初步理解了 Json 数据包的格式及用法。希望以后可以做出更为复杂的应用。

通过ESP8266WiFi模块调用“心知天气”接口 获取天气信息的更多相关文章

  1. JS调用腾讯接口获取天气

    想做个直接通过JS获取某个城市的天气.本来想通过直接调用中国气象网的接口: http://www.weather.com.cn/weather/101070201.shtml,但是跨域问题一直无法解决 ...

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

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

  3. 使用小米天气API获取天气信息

    1. URL部分 以下url中"%s"代表的是城市Id,比如北京的cityId=101010100: //获取未来五天预报信息,红色部分信息不需要 WEATHER_DATA_URL ...

  4. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:通过接口获取实时信息

    对于动态网站,要实时更新网站的信息,通过接口来获取实时信息是一个必不可少的部分.EasyNVR可以接入IPC等前端设备,必须要实时获取到对应的IPC实时信息进行展示. 本篇主要说明Ajax来获取数据. ...

  5. C# 调用腾讯云接口获取视频基本信息

    做项目需要上传视频,获取时长,上传教程很多,获取信息很少,官方只有一条请求地址. 找了好久,都没有说这个请求地址怎么用.最后发现需要调用腾讯云SDK 官方地址:https://github.com/Q ...

  6. Java接口获取系统配置信息

    Java获取当前运行系统的配置信息 接口:System.getProperty() 参数 描述 java.version Java运行时环境版本 java.vendor Java运行时环境供应商 ja ...

  7. android之location 根据接口获取经纬度信息

    http://maps.googleapis.com/maps/api/geocode/json?address=%E7%A6%8F%E5%BB%BA&sensor=falsehttp://m ...

  8. android从中国天气网获取天气

    http://download.csdn.net/detail/sun6223508/8011669      里面的一切..可完全移植 版权声明:本文博主原创文章.博客,未经同意不得转载.

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

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

  10. Python3基础(4)匿名函数、装饰器、生成器、迭代器、内置函数、json&pickle序列化、软件目录开发规范、不同目录间模块调用

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...

随机推荐

  1. 练习_使用递归计算1-n之间的和-练习_使用递归计算阶乘

    练习_使用递归计算1-n之间的和 定义一个方法,使用递归计算1-n之间的和 1+2+3+. . .+n n+(n-1)+(n-2)+...+1 已知: 最大值:n 最小值:1 使用递归必须明确: 1. ...

  2. 前端基础知识-html(一)个人学习记录

    待补充 块级元素与行内元素,常见举例 html5新特性?

  3. pycharm设置python头文件模版

    钢铁知识库,一个学习python爬虫.数据分析的知识库.人生苦短,快用python. 使用pycharm创建python文件时候,有时候需要自动生成想要的文件头,如何生成呢? 只需要以下几步: 在fi ...

  4. 12月19日内容总结——Q查询进阶、ORM查询优化、ORM事务、ORM常用字段类型和字段参数、Ajax介绍、数据编码格式、Ajax携带文件数据

    目录 一.Q查询进阶操作 二.ORM查询优化 三.ORM事务操作 四.ORM常用字段类型 五.ORM常用字段参数 六.Ajax AJAX简介 应用场景 AJAX的优点 语法实现 七.数据编码格式(Co ...

  5. 重学SpringBoot. step4 Redis的应用

    Redis的应用 Redis支持的七种数据类型:字符串.散列.列表(链表).集合.有序集合.基数和地理位置,具体用Java怎么操作其实可以直接看redisTemplate的源代码. Redis引出来的 ...

  6. 【Windows】ip地址修改器v5.0.5.4 修改ip更简便

    ip地址修改器v5.0.5.4 修改ip更简便 IP地址修改器,一款能够快速的切换IP地址,在几个不同的固定IP之间进行切换,手动输太麻烦,所以可以用到这款IP地址修改器! 下载 ip地址修改器v5. ...

  7. vue3 vite 使用NProgress.js纳米级进度条

    NProgress.js 官网:https://ricostacruz.com/nprogress/ 安装方式: npm install nprogress 使用方法 在router 的index.j ...

  8. ClickHouse exception, code: 62, host: hadoop102, port: 8123; Code: 62, e.displayText() = DB::Exception: Syntax error: failed at position 183 (end of query):

    报错 ClickHouse exception, code: 62, host: hadoop102, port: 8123; Code: 62, e.displayText() = DB::Exce ...

  9. windows定时任务执行python爬虫

    有一些定时爬取的操作,适合用定时任务去执行.个人单独用的项目不适合放在工作所用的服务器上,也没必要单独买个服务器,我们windows电脑本身就有这项功能.接下来是一个windows定时任务执行pyth ...

  10. PPMM

    代码 #include<cstdio> using namespace std; const int N = 1000000 , INF = 2e9; int n , m , x , he ...