1. 程式人生 > 其它 >ESP8266使用WiFi模組呼叫心知天氣API獲取天氣資料

ESP8266使用WiFi模組呼叫心知天氣API獲取天氣資料

ESP8266使用WiFi模組呼叫心知天氣API獲取天氣資料

安裝 ArduinoJson 庫

儘量使用 ArduinoJson 5.x 版本,因為 6.x 版本有很大的改動。

申請“心知天氣”的個人APIKEY

心知天氣官網

註冊成功後選擇免費版

去免費版裡面複製自己的私鑰

把程式碼中的可變選項替換成自己的私鑰、網路名稱和密碼,程式碼如下:

#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";
//初始化
void setup() {
  Serial.begin(BAUD_RATE);
  wifiConnect();//連線WiFi
  client.setTimeout(HTTP_TIMEOUT);
}

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);
}
}

//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());
}

//傳送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;
}

//跳過響應頭
bool skipResponseHeaders(){
  bool ok=client.find(endOfHeaders);
  if(!ok){
    Serial.println("No response of invalid response!");
  }
  return ok;
}

//讀取響應的正文資訊
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();//重新整理客戶端
}

//分析 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;
}

//串列埠輸出
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);
}
//停止客戶端訪問
void stopConnect(){
  Serial.println("Disconnect");
  client.stop();//停止客戶端訪問
}
//清除快取
void clrEsp8266ResponseBuffer(void){
  memset(response,0,MAX_CONTENT_SIZE);
}

程式碼還需課後多理解一下。這樣就能使用ESP8266的WiFi模組呼叫心知天氣API獲取天氣資料了。