ESP8266 显示实时天气信息

Posted h4lo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ESP8266 显示实时天气信息相关的知识,希望对你有一定的参考价值。

代码文件

技术图片

getdata.h

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>

#define DEBUG 1
#define MAX_CONTENT_SIZE 2000


const char* ssid = "***";                // wifi 账号密码
const char* password = "****";

WiFiClient client;
HTTPClient http;
char response[MAX_CONTENT_SIZE];
    
const char* HOST = "api.seniverse.com";
const char* APIKEY = "***";    // 心知天气接口私钥
const char* CITY = "haikou";


typedef struct UserData{
    char city[16];
    char weather[32];
    char temp[16];
}data;

data d;

bool parseData(data &d);
data getdata();
bool WifiConfig();
void weather_init();
bool sendRequest(const char* host, const char* cityid, const char* apiKey);
void clearResponseBuffer();
    

void clearResponseBuffer(){
    memset(response, 0, MAX_CONTENT_SIZE);      //清空
    memset(d.city,0,sizeof(d.city));
    memset(d.weather,0,sizeof(d.weather));
    memset(d.temp,0,sizeof(d.temp));
}

data getdata(){
    
    char error[5] = "NULL";
    clearResponseBuffer();
    
    if(sendRequest(HOST,CITY,APIKEY)){
        Serial.println("Request success!\\n\\n");
    }
    if(parseData(d)){
        return d;
    }else{
        strcpy(d.city,error);
        strcpy(d.weather,error);
        strcpy(d.temp,error);
        
        return d;
    }
}


bool WifiConfig(){
    WiFi.begin(ssid,password);
    
    while (WiFi.status() != WL_CONNECTED){
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("Connected success!");
    Serial.println("");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    
    return true;
}

bool parseData(data &d){
    
    DynamicJsonBuffer jsonBuffer;
  
    JsonObject& root = jsonBuffer.parseObject(response);
    
    if(!root.success()){
        Serial.println("JSON parse failed!\\n");
        return false;
    }
    
    strcpy(d.city,root["results"][0]["location"]["name"]);
    strcpy(d.weather,root["results"][0]["now"]["text"]);
    strcpy(d.temp,root["results"][0]["now"]["temperature"]);
    
    return true;
}

bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
    
    //const char *response;
    char *Url = (char *)malloc(0x100);
    String payload;
    
    sprintf(Url,"%s%s%s%s%s%s%s","http://",host,"/v3/weather/now.json?key=",apiKey,"&location=",cityid,"&language=en");
    Serial.printf("GET URL: %s\\n",Url);
    
    
    http.begin(Url);
    int httpCode = http.GET();
    if(httpCode>0){
        Serial.printf("[HTTP] GET... code: %d\\n",httpCode);
    
        if(httpCode == HTTP_CODE_OK){
            payload = http.getString();
            Serial.println(payload);
        }else{
            return false;
        }
    }else{
        Serial.println("Something error!");
        return false;
    }
    strcpy(response,payload.c_str());       // convert to const char *
    free(Url);
    return true;
}


void weather_init(){
    WifiConfig();
}

配置完 wifi 之后,请求心知天气的 API 接口,得到 JSON 数据之后,解析返回主代码文件。

主代码文件(.ino)

得到返回的数据体解析并显示在屏幕上(drawstring),5s 钟更新一次。

#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
// For a connection via I2C using brzo_i2c (must be installed) include
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
// #include "SSD1306Brzo.h"
// #include "SH1106Brzo.h"


#include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Spi.h"
// #include "SH1106SPi.h"

#include "images.h"

// Initialize the OLED display using SPI
// D5 -> CLK
// D7 -> MOSI (DOUT)
// D0 -> RES
// D2 -> DC
// D8 -> CS
SSD1306Spi        display(D0, D2, D8);
// or
// SH1106Spi         display(D0, D2);

// Initialize the OLED display using brzo_i2c
// D3 -> SDA
// D5 -> SCL
// SSD1306Brzo display(0x3c, D3, D5);
// or
// SH1106Brzo  display(0x3c, D3, D5);

// Initialize the OLED display using Wire library
//SSD1306Wire  display(0x3c, D3, D5);
// SH1106 display(0x3c, D3, D5);

#include "getdata.h"


#define DEMO_DURATION 3000

typedef void (*Demo)(void);

int demoMode = 0;
int counter = 1;

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  weather_init();
  

  // Initialising the UI will init the display too.
  display.init();

  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);

}

void drawFontFaceDemo() {

    char city[10];
    char weather[20];
    char temp[10];
    
    sprintf(city,"%s: %s","City",getdata().city);
    sprintf(weather,"%s: %s","Weather",getdata().weather);
    sprintf(temp,"%s: %s","temp",getdata().temp);
    
  
    // create more fonts at http://oleddisplay.squix.ch/


    display.setFont(ArialMT_Plain_16);
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.drawString(10, 0, city);
    display.drawString(0, 20, weather);
    display.drawString(0, 40, temp);
    
}

void drawTextFlowDemo() {
    display.setFont(ArialMT_Plain_10);
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.drawStringMaxWidth(0, 0, 128,
      "Lorem ipsum\\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." );
}

void drawTextAlignmentDemo() {
    // Text alignment demo
  display.setFont(ArialMT_Plain_10);

  // The coordinates define the left starting point of the text
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(0, 10, "Left aligned (0,10)");

  // The coordinates define the center of the text
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 22, "Center aligned (64,22)");

  // The coordinates define the right end of the text
  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(128, 33, "Right aligned (128,33)");
}

void drawRectDemo() {
      // Draw a pixel at given position
    for (int i = 0; i < 10; i++) {
      display.setPixel(i, i);
      display.setPixel(10 - i, i);
    }
    display.drawRect(12, 12, 20, 20);

    // Fill the rectangle
    display.fillRect(14, 14, 17, 17);

    // Draw a line horizontally
    display.drawHorizontalLine(0, 40, 20);

    // Draw a line horizontally
    display.drawVerticalLine(40, 0, 20);
}

void drawCircleDemo() {
  for (int i=1; i < 8; i++) {
    display.setColor(WHITE);
    display.drawCircle(32, 32, i*3);
    if (i % 2 == 0) {
      display.setColor(BLACK);
    }
    display.fillCircle(96, 32, 32 - i* 3);
  }
}

void drawProgressBarDemo() {
  int progress = (counter / 5) % 100;
  // draw the progress bar
  display.drawProgressBar(0, 32, 120, 10, progress);

  // draw the percentage as String
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 15, String(progress) + "%");

  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_10);
  display.drawString(10, 0, "H4lo nb!");
}

void drawImageDemo() {
    // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html
    // on how to create xbm files
    display.drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
}

//Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo, drawImageDemo};
Demo demos[] = {drawFontFaceDemo};
int demoLength = (sizeof(demos) / sizeof(Demo));
long timeSinceLastModeSwitch = 0;

void loop() {
  // clear the display
  display.clear();
 
  demos[demoMode]();
  delay(5000);    //延迟

  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(10, 128, String(millis()));
  // write the buffer to the display
  display.display();

  if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
    demoMode = (demoMode + 1)  % demoLength;
    timeSinceLastModeSwitch = millis();
  }
  counter++;
  delay(10);
}

效果

技术图片

以上是关于ESP8266 显示实时天气信息的主要内容,如果未能解决你的问题,请参考以下文章

利用ESP8266+OLED(I2C)打造智能时钟(网络校时+实时天气+天气预报)

TFT 触控屏 + ESP8266 制造天气时钟

esp8266气象站2

Arduino ESP8266利用HTTPClient库 获取心知天气请求实例

0.96“OLED+ESP8266天气时钟+古诗农历显示

ESP8266环境监测系统+制作手机App在线实时显示