esp8266初级入门实用教程一之访问心知天气读取实时天气数据

ESP8266作为一款功能强大的的物联网模块,已经被应用到了很多实用的物联网项目中。作为一个菜鸟,本人也捣鼓这个东西很长时间了,在捣鼓这个东西的同时我也总结了一些使用经验。在此借助CSDN平台出几个教程,将这些经验分享给大家,同时也做为个人的实践经验总结。

ESP8266的主要开发方式有三种:官方SDK(深圳乐鑫的官方库+深圳安信可的类eclipse开发环境),lua语言以及arduino的ESP8266库。楼主经常使用第一种和第三种(对lua不太熟悉),对于新手而言官方的SDK开发还是比较晦涩难懂的,教程也不是很多(B站技新课堂基于官方SDK的ESP8266视频教程比较不错,有兴趣的可以去了解),因此本esp8266初级入门实用教程还是使用arduino进行开发,需要大家配置好arduino中ESP8266的开发环境并对arduino的ESP8266库有一定的了解。(大家可以去搜单片机菜鸟博哥的教程,私以为是我看过的基于arduino的最好的ESP8266文本教程)。

第一个实践教程当然是从大家喜闻乐见的读取网络实时天气开始,这个搞明白的话,大家基本上也就会对物联网有一个感性的认识了。实现该项目的主要步骤如下:

(一)注册心知天气账户,申请天气数据AP免费版并记下访问私钥。

esp8266初级入门实用教程一之访问心知天气读取实时天气数据_第1张图片

                                                                      打开心知天气官网后进行注册和登录。

esp8266初级入门实用教程一之访问心知天气读取实时天气数据_第2张图片

                                                                                  申请天气数据API免费版

esp8266初级入门实用教程一之访问心知天气读取实时天气数据_第3张图片

                                                                                           记下访问私钥

完成上述三个步骤我们就拥有了读取心知天气实时天气状况的权限,注意:免费版的访问数据是有限制的,访问频次每分钟只有20次,但对于我们而言已经够用了。

(二)了解HTTP协议,获取URL并确定最终访问格式。 

HTTP协议(超文本传输协议)是互联网上应用最为广泛的一种应用层网络协议,用作客户端和服务器之间的请求 - 响应协议,具体可参考此篇博文https://blog.csdn.net/weixin_34259559/article/details/87951549

HTTP协议中客户端的数据请求和上传主要依靠GET请求和POST请求进行。此次教程中我们只需要向服务器进行数据的请求,所以只讲GET请求及其请求格式。

HTTP协议中数据的请求格式包含请求行(request line)、请求头部(header)、空行和请求数据四个部分,下图给出了请求报文的一般格式:

esp8266初级入门实用教程一之访问心知天气读取实时天气数据_第4张图片

HTTP协议使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息。我们想读取心知天气的数据资源也必须知道它的URL,心知天气的文档中给我们提供了它的URL格式,如下图:

心知天气URL格式

 知道了HTTP报文的格式和心知天气的URL我们就可知得到最终的访问格式,如下:

URL是; /v3/weather/now.json?key=“你的私钥”&location=beijing&language=zh-Hans&unit=c HTTP/1.1\r\n
            //根据HTTP报文格式,在URL协议后面缀上协议版本HTTP/1.1

请求头部:
	主机名:Host: api.seniverse.com\r\n
	
 	接收的语言:Accept-Language: zh-cn\r\n
	
 	连接的模式-- 断开服务器连接:Connection: close\r\n
	

(三)程序编写,实现ESP8266访问心知天气并读取当前实时天气。

由于心知天气返回的是JSON字符串,需要进行数据解析,自写解析函数的话比较麻烦,这里我们使用前辈们已经为我们造好的轮子,JSON库。程序中的JSON数据解析我已经附上了B站的教程地址。

#include 
#include                  //使用JSON-v5版的库
 
const char* AP_SSID     = "644";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* AP_PSK = "@644.1234";        // XXXXXX -- 使用时请修改为当前你的 wifi 密码

WiFiClient client;                       //创建一个网络对象

/*  请求的Json数据格式如下:
 * {
 *    "results": [
 *        {
 *            "location": {
 *                "id": "WX4FBXXFKE4F",
 *                "name": "北京",
 *                "country": "CN",
 *                "path": "北京,北京,中国",
 *                "timezone": "Asia/Shanghai",
 *                "timezone_offset": "+08:00"
 *            },
 *            "now": {
 *                "text": "多云",
 *                "code": "4",
 *                "temperature": "23"
 *            },
 *            "last_update": "2019-10-13T09:51:00+08:00"
 *        }
 *    ]
 *}
 */

void wifi_start_connect()              //连接WIFI
{
  WiFi.mode(WIFI_STA);                 //设置esp8266 工作模式 
  Serial.println("Connecting to ");    //写几句提示
  Serial.println(AP_SSID);
  WiFi.begin(AP_SSID, AP_PSK);         //连接wifi
  WiFi.setAutoConnect(true);
  while (WiFi.status()!= WL_CONNECTED) //这个函数是wifi连接状态,返回wifi链接状态
        {  
         delay(500);
         Serial.print(".");
        }
  Serial.println("WiFi connected IP is");
  Serial.println(WiFi.localIP()); 
}

void parseUserData(String content)  // Json数据解析并串口打印.可参考https://www.bilibili.com/video/av65322772
{
 const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
 DynamicJsonBuffer jsonBuffer(capacity);

 JsonObject& root = jsonBuffer.parseObject(content);

 JsonObject& results_0 = root["results"][0];

 JsonObject& results_0_location = results_0["location"];
 const char* results_0_location_id = results_0_location["id"];
 const char* results_0_location_name = results_0_location["name"];
 const char* results_0_location_country = results_0_location["country"];
 const char* results_0_location_path = results_0_location["path"];
 const char* results_0_location_timezone = results_0_location["timezone"];
 const char* results_0_location_timezone_offset = results_0_location["timezone_offset"];

 JsonObject& results_0_now = results_0["now"];
 const char* results_0_now_text = results_0_now["text"];
 const char* results_0_now_code = results_0_now["code"];
 const char* results_0_now_temperature = results_0_now["temperature"];
 const char* results_0_last_update = results_0["last_update"];

 Serial.println(results_0_location_name);                       //通过串口打印出需要的信息
 Serial.println(results_0_now_text);
 Serial.println(results_0_now_code);
 Serial.println(results_0_now_temperature);
 Serial.println(results_0_last_update);
 Serial.print("\r\n");
}

void setup() 
{
 Serial.begin(115200); 
 wifi_start_connect(); 
 client.setTimeout(5000);//设置服务器连接超时时间
}

void loop() 
{                            
if(client.connect("api.seniverse.com", 80)==1)              //连接服务器并判断是否连接成功,若成功就发送GET 请求数据下发       
  {                                           //换成你自己在心知天气申请的私钥//改成你所在城市的拼音
   client.print("GET /v3/weather/now.json?key=“你的私钥”&location=zhengzhou&language=zh-Hans&unit=c HTTP/1.1\r\n"); //心知天气的URL格式          
   client.print("Host:api.seniverse.com\r\n");
   client.print("Accept-Language:zh-cn\r\n");
   client.print("Connection:close\r\n\r\n"); //向心知天气的服务器发送请求。

                 
   String status_code = client.readStringUntil('\r');        //读取GET数据,服务器返回的状态码,若成功则返回状态码200
   Serial.println(status_code);
      
   if(client.find("\r\n\r\n")==1)                            //跳过返回的数据头,直接读取后面的JSON数据,
     {
      String json_from_server=client.readStringUntil('\n');  //读取返回的JSON数据
      Serial.println(json_from_server);
      parseUserData(json_from_server);                      //将读取的JSON数据,传送到JSON解析函数中进行显示。
     }
  }
else                                        
  { 
   Serial.println("connection failed this time");
   delay(5000);                                            //请求失败等5秒
  } 
     
client.stop();                                            //关闭HTTP客户端,采用HTTP短链接,数据请求完毕后要客户端要主动断开https://blog.csdn.net/huangjin0507/article/details/52396580
delay(5000);         
}

(四)实际演示;

esp8266初级入门实用教程一之访问心知天气读取实时天气数据_第5张图片

我们可以清楚的看到ESP8266成功的读取到了当前天气数据,并通过串口打印了出来。

(五)总结

本次教程只是做了一个走马观花式的粗略演示(有错误也请各位指出,相互交流),无论是其中的HTTP协议还是JSON解析都可以再引出一大波知识点,这些都需要各位自己去搜索资料学习。 接下来我会更新一些ESP8266使用HTTP和MQTT协议与ONENET交互的教程(楼主作为懒癌晚期患者,就随缘吧)。

你可能感兴趣的:(物联网,ESP8266,arduino)