esp8266气象站2

Posted beyondsdo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了esp8266气象站2相关的知识,希望对你有一定的参考价值。

承接上一篇,使用的数据源仍然是心知天气提供的数据接口,可以每分钟查询20次,也就是做多3s请求一次数据

替换原有的nodemcu,使用了ttgo-display,芯片esp32,自带一个1.14‘的ips显示屏

2,实现查询最近三天的天气信息,串口终端以及tft显示,界面还有问题,下次换屏。

    通过轮询的方式查询多地的天气,

3,存在的问题,tft_espi显示函数不太熟悉,缺少全面的函数调用说明/应该可以找到吧,依然是一个测试版本。

4,改进,下一版本准备中文字库,或许添加图标

/* esp32 weather station
 *  191130,ver2
 * ttgo_版本,同时查询四个城市的天气状况,使用心天气api
 * 串口打印所有的天气信息
 * 适配ttgo屏幕
*/
// Libraries
//#include <ESP8266WiFi.h>
#include <WiFi.h>     //esp32used
#include <HTTPClient.h>
#include <ArduinoJson.h> //使用ArduinoJson库
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include <Button2.h>

#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif

#ifndef TFT_SLPIN
#define TFT_SLPIN   0x10
#endif

#define TFT_MOSI            19
#define TFT_SCLK            18
#define TFT_CS              5
#define TFT_DC              16
#define TFT_RST             23

#define TFT_BL          4  // Display backlight control pin
#define ADC_EN          14
#define ADC_PIN         34
#define BUTTON_1        35
#define BUTTON_2        0

#define TFT_GREY 0x5AEB // New colour
#define MAX_CONTENT_SIZE 2000

TFT_eSPI tft = TFT_eSPI(135,240);  // Invoke library, pins defined in User_Setup.h

Button2 btn1(BUTTON_1);
Button2 btn2(BUTTON_2);

int btnCick = false;

// WiFi settings
const char* ssid     = "xxxxxx";
const char* password = "12345677";
// API server
const char* host = "api.seniverse.com";

const char*  API_key = "xyMNfwsL07QDmljCq";
//查询城市
const char* req_city0 = "hangzhou";
const char* req_city1 = "jilin";
const char* req_city2 = "hefei";
const char* req_city3 = "wuhan";
//选择语言
//const char* language = "en";
const char* language = "zh-Hans";


String weather_data;
HTTPClient http;
char response[MAX_CONTENT_SIZE];

//
void espDelay(int ms)
{   
    esp_sleep_enable_timer_wakeup(ms * 1000);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH,ESP_PD_OPTION_ON);
    esp_light_sleep_start();
}
//---------------------------------------------按键操作函数
/*
void button_init()
{
    btn1.setLongClickHandler([](Button2 & b) {
        btnCick = false;
        int r = digitalRead(TFT_BL);
        tft.fillScreen(TFT_BLACK);
        tft.setTextColor(TFT_GREEN, TFT_BLACK);
        tft.setTextDatum(MC_DATUM);
        tft.drawString("Press again to wake up",  tft.width() / 2, tft.height() / 2 );
        espDelay(6000);
        digitalWrite(TFT_BL, !r);

        tft.writecommand(TFT_DISPOFF);
        tft.writecommand(TFT_SLPIN);
        esp_sleep_enable_ext1_wakeup(GPIO_SEL_35, ESP_EXT1_WAKEUP_ALL_LOW);
        esp_deep_sleep_start();
    });
    btn1.setPressedHandler([](Button2 & b) {
        Serial.println("Detect Voltage..");
        btnCick = true;
    });

    btn2.setPressedHandler([](Button2 & b) {
        btnCick = false;
        Serial.println("btn press wifi scan");
        wifi_scan();
    });
}

void button_loop()
{
    btn1.loop();
    btn2.loop();
}
*/
//-------------------------------连接wifi设置
void connect_wifi(){
  Serial.print("Connecting to WIFI");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  }
//----------------------------------------------------连接到服务器
void connect_API(){
  // Connect to API
  Serial.print("connecting to XinZhi");
  Serial.println(host);
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
   }
  }
//----------------------------------------------------获取返回数据
String sendRequest(const char* host, const char* cityid, const char* apiKey) {
    
    //const char *response;
    char *Url = (char *)malloc(0x100);
    String payload;
    //https://api.seniverse.com/v3/weather/daily.json?key=SyMNfwsL07QDmljCq&location=beijing&language=zh-Hans&unit=c&start=0&days=3
    sprintf(Url,"%s%s%s%s%s%s%s","http://",host,"/v3/weather/daily.json?key=",apiKey,"&location=",cityid,"&language=en&unit=c&start=0&days=3");
    Serial.printf("GET URL: %s
",Url);
    
    
    http.begin(Url);
    int httpCode = http.GET();
    if(httpCode>0){
        Serial.printf("[HTTP] GET... code: %d
",httpCode);
        
        if(httpCode == 200){
            payload = http.getString();
            Serial.println(payload);
        }else{
            delay(5000);
            sendRequest(host,cityid,apiKey);
        }
    }else{
        delay(5000);
            sendRequest(host,cityid,apiKey);
    }
    strcpy(response,payload.c_str());       // convert to const char *
    free(Url);
    return payload;
}
//----------------------------------------------------切片解析来自arduino jason
void process_jason(String  jason_data){
  // Process weather_json
////  Serial.println();
 // Serial.println("jason_data: ");
 //  Serial.println(jason_data);
 
  // Convert to JSON
  String json_weather_data;
  int jsonIndex;
 
  for (int i = 0; i < jason_data.length(); i++) {
    if (jason_data[i] == {) {
      jsonIndex = i;
      break;
    }
  }
 
  // Get JSON data
  json_weather_data = jason_data.substring(jsonIndex);
//  Serial.println();
//  Serial.println("json_weather_data: ");
//  Serial.println(json_weather_data);
 
 
  //利用arduinoJson库解析心知返回的json天气数据
  //可以利用 https://arduinojson.org/v5/assistant/ Arduinojson助手生成相关json解析代码  很方便!!!
  const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 3*JSON_OBJECT_SIZE(12) + 720;
DynamicJsonBuffer jsonBuffer(capacity);

//const char* json = "{"results":[{"location":{"id":"WTMKQ069CCJ7","name":"杭州","country":"CN","path":"杭州,杭州,浙江,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2019-06-30","text_day":"暴雨","code_day":"16","text_night":"中雨","code_night":"14","high":"29","low":"25","precip":"","wind_direction":"北","wind_direction_degree":"0","wind_speed":"15","wind_scale":"3"},{"date":"2019-07-01","text_day":"中雨","code_day":"14","text_night":"中雨","code_night":"14","high":"27","low":"24","precip":"","wind_direction":"无持续风向","wind_direction_degree":"","wind_speed":"10","wind_scale":"2"},{"date":"2019-07-02","text_day":"小雨","code_day":"13","text_night":"小雨","code_night":"13","high":"24","low":"22","precip":"","wind_direction":"东","wind_direction_degree":"90","wind_speed":"15","wind_scale":"3"}],"last_update":"2019-06-30T11:00:00+08:00"}]}";

JsonObject& root = jsonBuffer.parseObject(json_weather_data);

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

JsonObject& results_0_location = results_0["location"];
const char* results_0_location_id = results_0_location["id"]; // "WTMKQ069CCJ7"
const char* results_0_location_name = results_0_location["name"]; // "杭州"
const char* results_0_location_country = results_0_location["country"]; // "CN"
const char* results_0_location_path = results_0_location["path"]; // "杭州,杭州,浙江,中国"
const char* results_0_location_timezone = results_0_location["timezone"]; // "Asia/Shanghai"
const char* results_0_location_timezone_offset = results_0_location["timezone_offset"]; // "+08:00"
    
    tft.println(results_0_location_name);
JsonArray& results_0_daily = results_0["daily"];

JsonObject& results_0_daily_0 = results_0_daily[0];
const char* results_0_daily_0_date = results_0_daily_0["date"]; // "2019-06-30"
const char* results_0_daily_0_text_day = results_0_daily_0["text_day"]; // "暴雨"
const char* results_0_daily_0_code_day = results_0_daily_0["code_day"]; // "16"
const char* results_0_daily_0_text_night = results_0_daily_0["text_night"]; // "中雨"
const char* results_0_daily_0_code_night = results_0_daily_0["code_night"]; // "14"
const char* results_0_daily_0_high = results_0_daily_0["high"]; // "29"
const char* results_0_daily_0_low = results_0_daily_0["low"]; // "25"
const char* results_0_daily_0_precip = results_0_daily_0["precip"]; // ""
const char* results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"]; // "北"
const char* results_0_daily_0_wind_direction_degree = results_0_daily_0["wind_direction_degree"]; // "0"
const char* results_0_daily_0_wind_speed = results_0_daily_0["wind_speed"]; // "15"
const char* results_0_daily_0_wind_scale = results_0_daily_0["wind_scale"]; // "3"
 
JsonObject& results_0_daily_1 = results_0_daily[1];
const char* results_0_daily_1_date = results_0_daily_1["date"]; // "2019-07-01"
const char* results_0_daily_1_text_day = results_0_daily_1["text_day"]; // "中雨"
const char* results_0_daily_1_code_day = results_0_daily_1["code_day"]; // "14"
const char* results_0_daily_1_text_night = results_0_daily_1["text_night"]; // "中雨"
const char* results_0_daily_1_code_night = results_0_daily_1["code_night"]; // "14"
const char* results_0_daily_1_high = results_0_daily_1["high"]; // "27"
const char* results_0_daily_1_low = results_0_daily_1["low"]; // "24"
const char* results_0_daily_1_precip = results_0_daily_1["precip"]; // ""
const char* results_0_daily_1_wind_direction = results_0_daily_1["wind_direction"]; // "无持续风向"
const char* results_0_daily_1_wind_direction_degree = results_0_daily_1["wind_direction_degree"]; // ""
const char* results_0_daily_1_wind_speed = results_0_daily_1["wind_speed"]; // "10"
const char* results_0_daily_1_wind_scale = results_0_daily_1["wind_scale"]; // "2"
 
JsonObject& results_0_daily_2 = results_0_daily[2];
const char* results_0_daily_2_date = results_0_daily_2["date"]; // "2019-07-02"
const char* results_0_daily_2_text_day = results_0_daily_2["text_day"]; // "小雨"
const char* results_0_daily_2_code_day = results_0_daily_2["code_day"]; // "13"
const char* results_0_daily_2_text_night = results_0_daily_2["text_night"]; // "小雨"
const char* results_0_daily_2_code_night = results_0_daily_2["code_night"]; // "13"
const char* results_0_daily_2_high = results_0_daily_2["high"]; // "24"
const char* results_0_daily_2_low = results_0_daily_2["low"]; // "22"
const char* results_0_daily_2_precip = results_0_daily_2["precip"]; // ""
const char* results_0_daily_2_wind_direction = results_0_daily_2["wind_direction"]; // "东"
const char* results_0_daily_2_wind_direction_degree = results_0_daily_2["wind_direction_degree"]; // "90"
const char* results_0_daily_2_wind_speed = results_0_daily_2["wind_speed"]; // "15"
const char* results_0_daily_2_wind_scale = results_0_daily_2["wind_scale"]; // "3"
 
const char* results_0_last_update = results_0["last_update"]; // "2019-06-30T11:00:00+08:00"
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }
//串口显示
  Serial.println();
  Serial.print("城市: ");
  Serial.println(results_0_location_name);
  Serial.print("今天天气: ");
  Serial.print(results_0_daily_0_text_day);
  Serial.print("今天气温: ");
  Serial.print( results_0_daily_0_low);
  Serial.print("~");
  Serial.println( results_0_daily_0_high);
  Serial.print("明天天气: ");
  Serial.print(results_0_daily_1_text_day);
  Serial.print("明天气温: ");
  Serial.print( results_0_daily_1_low);
  Serial.print("~");
  Serial.println( results_0_daily_1_high);
  Serial.print("后天天气: ");
  Serial.print(results_0_daily_2_text_day);
  Serial.print("后天气温: ");
  Serial.print( results_0_daily_2_low);
  Serial.print("~");
  Serial.println( results_0_daily_2_high);

  Serial.print("风向:");
  Serial.print(results_0_daily_2_wind_direction);
  Serial.print("  风速:");
  Serial.print( results_0_daily_2_wind_speed);
  Serial.print("  风力:");
  Serial.println( results_0_daily_2_wind_scale);
//液晶显示
    tft.fillScreen(TFT_WHITE);
    tft.setTextColor(TFT_RED);
   // tft.setTextSize(2);
  //  tft.setTextFont(3);
    
    tft.drawString(results_0_location_name, 0, 0, 4);
    tft.drawString("day:", 0, 26, 4);   tft.drawString(results_0_daily_0_text_day, 70, 26, 4);
    tft.drawString("night:", 0, 52, 4); tft.drawString(results_0_daily_0_text_night, 70, 52, 4);
   //  tft.setTextColor(TFT_BLUE);tft.setTextFont(1);
    tft.drawString("temp1:", 0, 78, 4); tft.drawString(results_0_daily_0_low, 80, 78, 4);tft.drawString(results_0_daily_0_high, 130, 78, 4);
  //  tft.setTextColor(TFT_GREEN);tft.setTextFont(2);
    tft.drawString("temp2:", 0, 104, 4);tft.drawString(results_0_daily_1_low, 80, 104, 4);tft.drawString(results_0_daily_1_high, 130, 104, 4);
  //  tft.setTextColor(TFT_BLACK);tft.setTextFont(4);
    tft.drawString("temp3:", 0, 130, 4);tft.drawString(results_0_daily_2_low, 80, 130, 4);tft.drawString(results_0_daily_2_high, 130, 130, 4);
   // delay(WAIT);
 }
//----------------------------------------------------
void setup() {
  // Serial
  Serial.begin(115200);
  delay(10);
  tft.init();
  tft.setRotation(1);  //显示方向
  tft.fillScreen(TFT_BLACK);
  
  connect_wifi();//连接wifi

  //tft.setCursor(0, 0, 2);
  tft.setTextColor(TFT_WHITE,TFT_BLACK);
  tft.drawCentreString("connecting wifi", 0, 0, 3);
  
   delay(100);
}

void loop() {

  tft.fillScreen(TFT_WHITE);
 // tft.setCursor(0, 0, 2);//2font

    tft.setTextColor(TFT_RED);
 //   tft.setTextSize(2);
 //   tft.setTextFont(1);
    
  connect_API();
 // req_data(req_city1,language);
  weather_data = sendRequest(host, req_city0, API_key);
  process_jason(weather_data);
   
  delay(15000);
  delay(15000);
 
  weather_data = sendRequest(host, req_city1, API_key);
  process_jason(weather_data);
   
  delay(15000);
  delay(15000);
  weather_data = sendRequest(host, req_city2, API_key);
  process_jason(weather_data);
    
  delay(15000);
  delay(15000);
  weather_data = sendRequest(host, req_city3, API_key);
  process_jason(weather_data);
    


  //-------------------------------------打印结果

 
  // Wait 5 seconds
  delay(15000);
  delay(15000);

}

 

以上是关于esp8266气象站2的主要内容,如果未能解决你的问题,请参考以下文章

esp8266气象站2

ESP8266气象站+OLED图形库循环播放

基于ESP8266的简易气象站

esp8266气象站

ESP8266 Wifi芯片发送PHP GET请求但网站未收到

Arduino ESP32+OLED + 气象时钟+图形播放器