一、前言
接着[url=《博哥ESP8266系列1》- Arduino IDE for esp8266 http://www.geek-workshop.com/thread-30836-1-1.html (出处: 极客工坊)]上一篇[/url],这一次我们在配置好的环境下撸代码。之前说了,8266既然作为wifi模块,那么我们就可以进行一些网络请求。在我刚开始学Android的时候,最喜欢找一些免费的第三方接口去做一些小东西,这里也一样,我们直接用第三方API 心知天气 。具体的细节请到官网去参考文档,我只介绍其中一个API。我们用第三方接口的时候,免不了要注册以及使用到API_KEY,不想注册的同学直接使用楼主的密钥(wcmquevztdy1jpca),仅供学习参考用。
二、获取指定城市的实况天气
请求地址: https://api.thinkpage.cn/v3/weat ... guage=en&unit=c
请求方式:Get
1.首先,我们可以在浏览器直接打开以上网址,不出意外,应该有以下信息,也就是我们需要的信息。
[kenrobot_code]{
"results": [
{
"location": {
"id": "WS0E9D8WN298",
"name": "Guangzhou",
"country": "CN",
"path": "Guangzhou,Guangzhou,Guangdong,China",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"now": {
"text": "Sunny",
"code": "1",
"temperature": "26"
},
"last_update": "2017-09-13T23:05:00+08:00"
}
]
}[/kenrobot_code]
2.直接撸上我们的代码:
[kenrobot_code]/**
* 日期:2017/09/13
* 功能:在线获取天气数据情况 心知天气API
* 作者:单片机菜鸟
**/
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
const char* ssid = "360wifilulu"; // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* password = "6206908you11011010"; // XXXXXX -- 使用时请修改为当前你的 wifi 密码
const char* host = "api.seniverse.com";
const char* APIKEY = "wcmquevztdy1jpca"; //API KEY
const char* city = "guangzhou";
const char* language = "en";//zh-Hans 简体中文 会显示乱码
const unsigned long BAUD_RATE = 115200; // serial connection speed
const unsigned long HTTP_TIMEOUT = 5000; // max respone time from server
const size_t MAX_CONTENT_SIZE = 1000; // max size of the HTTP response
// 我们要从此网页中提取的数据的类型
struct UserData {
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";
/**
* @Desc 初始化操作
*/
void setup() {
WiFi.mode(WIFI_STA); //设置esp8266 工作模式
Serial.begin(BAUD_RATE);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");//写几句提示,哈哈
Serial.println(ssid);
WiFi.begin(ssid, password); //连接wifi
while (WiFi.status() != WL_CONNECTED) {
//这个函数是wifi连接状态,返回wifi链接状态
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
delay(500);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
client.setTimeout(HTTP_TIMEOUT);
}
/**
* @Desc 主函数
*/
void loop() {
while (!client.connected()){
if (!client.connect(host, 80)){
Serial.println("connection....");
delay(500);
}
}
if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
clrEsp8266ResponseBuffer();
readReponseContent(response, sizeof(response));
UserData userData;
if (parseUserData(response, &userData)) {
printUserData(&userData);
}
}
delay(5000);//每5s调用一次
}
/**
* @发送请求指令
*/
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");
Serial.println("create a request:");
Serial.println(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n");
delay(1000);
return true;
}
/**
* @Desc 跳过 HTTP 头,使我们在响应正文的开头
*/
bool skipResponseHeaders() {
// HTTP headers end with an empty line
bool ok = client.find(endOfHeaders);
if (!ok) {
Serial.println("No response or invalid response!");
}
return ok;
}
/**
* @Desc 从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 data Over!");
client.flush();//这句代码需要加上 不然会发现每隔一次client.find会失败
}
/**
* @Desc 解析数据
* 数据格式如下:
* {
* "results": [
* {
* "location": {
* "id": "WX4FBXXFKE4F",
* "name": "北京",
* "country": "CN",
* "path": "北京,北京,中国",
* "timezone": "Asia/Shanghai",
* "timezone_offset": "+08:00"
* },
* "now": {
* "text": "多云",
* "code": "4",
* "temperature": "23"
* },
* "last_update": "2017-09-13T09:51:00+08:00"
* }
* ]
*}
*/
bool parseUserData(char* content, struct UserData* userData) {
// -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
// 如果你使用StaticJsonBuffer时才需要
// const size_t BUFFER_SIZE = 1024;
// 在堆栈上分配一个临时内存池
// StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
// -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(content);
if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
//复制我们感兴趣的字符串
strcpy(userData->city, root["results"][0]["location"]["name"]);
strcpy(userData->weather, root["results"][0]["now"]["text"]);
strcpy(userData->temp, root["results"][0]["now"]["temperature"]);
strcpy(userData->udate, root["results"][0]["last_update"]);
// -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
// 当你读取字符串时它仍在内存中
return true;
}
// 打印从JSON中提取的数据
void printUserData(const struct UserData* userData) {
Serial.println("Print parsed data :");
Serial.print("City : ");
Serial.print(userData->city);
Serial.print(", \t");
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("Last Updata : ");
Serial.print(userData->udate);
Serial.println("\r\n");
}
// 关闭与HTTP服务器连接
void stopConnect() {
Serial.println("Disconnect");
client.stop();
}
void clrEsp8266ResponseBuffer(void){
memset(response, 0, MAX_CONTENT_SIZE); //清空
}[/kenrobot_code]
代码很熟悉有木有?是不是跟直接烧录Arduino一样。
这里我们用到了ArduinoJson库,不清楚的同学可以参考我这篇帖子 ArduinoJson库
然后把上面的代码烧录进你的Esp8266(楼主的是01)。没有意外的话,Esp8266处于工作模式时会打印出信息:
那么有人问了,该怎么连线呢?
硬件平台搭建:
1、硬件:可以选择以下的任一种
(1)ESP8266-01 ~13 + USB 转 TTL串口模块(如PL2303、CH340)
(2)ESP8266开发板或NodeMCU开发板 + USB数据线
硬件连接如下
ESP8266-01 ~13 + USB 转 TTL串口模块(如PL2303、CH340)
(1)如果wifi模块是ESP8266-01的按以下接线:(按烧写模式接线)
运行模式接线方法:(用USB转TTL串口连接模块与PC)
esp8266-01 u转串
VCC-----------3.3
GND----------GND
CH_PD--------3.3
RX-------------TX
TX-------------Rx
其余引脚为空。
烧写模式接线方法:烧写模式时需要将gpio0接地,工作模式时gpio0悬空
(注意有时8266需要独立供电,不直接在ttl取电,很多出现问题都在供电上,别对自己的电源太自信)
楼主的连接图(参考跑龙套帖子-http://www.arduino.cn/forum.php? ... =1&extra=#pid148026):
楼主这里用了一个Esp测试座,本质上还是上面的操作方式。附上一个测试座的讲解图:
硬件连接好了,就可以下载了,配置参考以下图。
点击上传,稍等一会下载完成。默认出现以下页面就是正常下载。
下载时可能会出现以下问题:
1.下载出错,可能没有进入到烧录模式
2.卡着不动,需重启一下8266,烧写模式时GPIO0接地,烧写完毕重启模块,GPIO0置空。
3.正确的下载的情况是ide通知栏是一串小点在增加,最后显示下载成功
三、总结
研究过程总会遇到各种问题,最重要淡定。
通过以上代码,我们就可以在线获取天气情况,既然能拿到天气信息,那么我们就可以在这基础上加入点显示功能,比如什么OLED 点阵屏等等。 |