Project tutorial
Get Current Weather Data from OpenWeatherMap.org

Get Current Weather Data from OpenWeatherMap.org © GPL3+

Get current weather data for any city on Earth from OpenWeatherMap.org.

  • 8,321 views
  • 1 comment
  • 24 respects

Components and supplies

Apps and online services

About this project

1. Project

Get current weather data for any city on Earth from OpenWeatherMap.org

2. Product

  • PHPoC WiFi Shield for Arduino (P4S-347)
  • Arduino MEGA2560
  • MDP070N Color LCD.

3. How it works

OpenWeatherMap.org gives current weather data us for free.

Refer to the link below for detail information of price plan. http://openweathermap.org/price

You have to sign up and create API key to get current weather data.

Data is in JSON, XML, or HTML format. In this project, I use JSON format.

4. Source code

"YOUR_API_KEY" should be replaced your own API key.

List city names in cityNames array variable.

E.g. char *cityNames[] = {"barcelona, es", "paris", "new york", "sydney", "london"};

Code

OpenWeatherMap.inoC/C++
#include <Arduino.h>
#include <Phpoc.h>
#include <SPI.h>
#include "Timer.h"

#include <ArduinoJson.h>

static PhpocClient phpocClient;

#define INTERVAL 4000

#define HTTP_QUERY_SIZE 1400
uint8_t httpQuery[HTTP_QUERY_SIZE];

int BUTTON_GPIO = 3;

char *server = "api.openweathermap.org";
char *apiKey = "YOUR_API_KEY";
char *cityNames[] = {"CITY_NAME,COUNTRY_CODE"};
char *currentWeather = "GET /data/2.5/weather?";

// Group 2xx: Thunderstorm  weather5.png
// Group 3xx: Drizzle  weather5.png
// Group 5xx: Rain  weather5.png

// Group 6xx: Snow  weather7.png

// Group 7xx: Atmosphere(안개)  weather2.png

// Group 800: CLEAR SKY. weather1.png

// Group 801: FEW CLOUDS. weather4.png
// Group 802: SCATTERED CLOUDS. weather2.png
// Group 803: BROKEN CLOUDS. weather3.png
// Group 804: OVERCAST CLOUDS. weather3.png

uint16_t queryLength = 0;
bool isRunning = false;
String httpResponse = "";
int numberOfCity = 0;

void setup() {
  // put your setup code here, to run once:  
  Serial.begin(115200);
  while (!Serial);// wait for serial port to connect.
  Serial.println();

  Serial1.begin(115200);
  while (!Serial1);// wait for serial port to connect.

  sendCmd("Clear\r\n");
  sendCmd("LoadFont \"/unbatang.ttf\"\r\n");

  Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
  Serial.println(Phpoc.localIP());

  numberOfCity = sizeof(cityNames) / sizeof(char*);
  
  // LCD
  initLCD();
}

void loop() {  
  // put your main code here, to run repeatedly:  
  apiLoop();
  httpLoop();
}

void apiLoop()
{
  static int index = 0;
  static unsigned long prevMills = 0;
  bool callApi = false;

  unsigned long currentMills = millis();
  if(prevMills == 0 || (currentMills - prevMills >= INTERVAL))
  {
    prevMills = currentMills;
    callApi = true;
  }

  if(callApi)
  {
    queryLength = getQueryCurrentWeather(httpQuery, cityNames[index++], apiKey);
    if(index >= numberOfCity)
      index = 0;
      
    httpResponse = "";
    if(phpocClient.connect(server, 80))
    {
      isRunning = true;
      phpocClient.write(httpQuery, queryLength);
    }
  }
}

char buf[1024];
String f = "\r\n\r\n";
void httpLoop()
{
  if(isRunning)  
  {
    uint16_t cnt = phpocClient.available();
    if(cnt > 0)
    {
      uint8_t tryRead = cnt > 128 ? 128 : cnt;
      memset(buf, 0, 1024);
      uint16_t recv = phpocClient.read(buf, tryRead);
      
      httpResponse = httpResponse + buf;      
      
      int idx = httpResponse.lastIndexOf(f);
      if(idx >= 0)
        httpResponse = httpResponse.substring(idx + 4);
    }
    
    if(!phpocClient.connected())
    {
      isRunning = false;
      sendCmd("DisableFlush");
      
      //----------------------------------------
      // JSON
      Serial.println(httpResponse.c_str());
      
      DynamicJsonBuffer jsonBuffer;
      JsonObject& root = jsonBuffer.parseObject(httpResponse);
      if(!root.success())
      {
        Serial.println("parseObject failed.");
        phpocClient.stop();
        isRunning = false;
        return;
      }
      
      uint16_t resultCode = root["cod"];
      Serial.println(resultCode);
      if(resultCode == 200)
      {
        //
        JsonObject& weather = root["weather"][0];
        String weatherId = weather["id"]; 
        String cityName = root["name"]; 
        double temperature = root["main"]["temp"]; 
        String temp = String(lround(temperature));
        String humidity = root["main"]["humidity"]; 
        String weatherDesc = weather["description"]; 

        printIcon(weatherId);
        printCity(cityName);
        printTemperature(temp);
        printHumidity(humidity);
        printWeather(weatherDesc);
        
        hidePopup();
      
        sendCmd("EnableLayer 1");
        sendCmd("EnableLayer 2");
        sendCmd("EnableLayer 3");
        sendCmd("EnableLayer 4");
        sendCmd("EnableLayer 5");
      }
      else
      {
        // fail.
      }
      //----------------------------------------
      
      Serial.println("disconnected");
      phpocClient.stop();
      sendCmd("EnableFlush");
    }
  }
}

uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos) 
{
    const char* idp = string;
    uint16_t i = 0;
 
    while (*idp) 
    {
        buf[pos++] = *idp++;
        i++;
    }
    
    return pos;
}

uint16_t getQueryCurrentWeather(uint8_t* query, char* cityName, char* apiKey)
{
  uint16_t queryLength = 0;

  queryLength = writeString(currentWeather, query, queryLength);
  queryLength = writeString("q=", query, queryLength);
  queryLength = writeString(cityName, query, queryLength);
  queryLength = writeString("&units=metric&appid=", httpQuery, queryLength);
  queryLength = writeString(apiKey, query, queryLength);  

  queryLength = writeString(" HTTP/1.1\r\nHost: api.openweathermap.org\r\n", query, queryLength);
  queryLength = writeString("Connection: Closed\r\n\r\n", query, queryLength);
  
  return queryLength;
}

void sendCmd(char* cmd)
{
  Serial1.println(cmd);
}

void initLCD()
{
  sendCmd("Layer 0");
  sendCmd("Clear");
  //sendCmd("LoadFont \"/unbatang.ttf\"");

  sendCmd("DestroyLayer 1");
  sendCmd("DestroyLayer 2");
  sendCmd("DestroyLayer 3");
  sendCmd("DestroyLayer 4");
  sendCmd("DestroyLayer 5");
  sendCmd("DestroyLayer 6");
  sendCmd("DestroyLayer 7");
  sendCmd("DestroyLayer 8");
  sendCmd("DestroyLayer 9");
  sendCmd("DestroyLayer 10");
  sendCmd("DestroyLayer 11");
  sendCmd("DestroyLayer 12");
  sendCmd("DestroyLayer 13");

  createLayers();
  createPopup();

  showPopup("Loading...");

  sendCmd("DisableFlush");
  sendCmd("Layer 0");
  sendCmd("FontSize 48");  
  sendCmd("Image 0 0 \"/image/bk3.png\"");
  sendCmd("EnableFlush");
}

void createLayers()
{
  // weather condition
  sendCmd("CreateLayer 68 380 732 70 1");  
  // ICON
  sendCmd("CreateLayer 68 108 265 245 2");
  // City name
  sendCmd("CreateLayer 460 60 320 80 3");
  // Temperature
  sendCmd("CreateLayer 460 170 340 120 4");
  // Humidity
  sendCmd("CreateLayer 460 310 340 70 5");
}

void createPopup()
{  
  sendCmd("CreateLayer 80 180 640 120 6");
  sendCmd("Layer 6");
  sendCmd("DisableLayer 6");
}

void showPopup(String msg)
{
  String cmd;
  sendCmd("Layer 6");
  sendCmd("Clear");
  sendCmd("FontSize 72");
  sendCmd("Color FFFFFF");
  cmd = "Button 0 0 640 120 10 336699 336699 \"" + msg + "\"";
  sendCmd(cmd.c_str());
  sendCmd("EnableLayer 6");
}

void hidePopup()
{
  sendCmd("DisableLayer 6");
}

void printCity(String cityName)
{
  String cmd;
  sendCmd("Layer 3");
  sendCmd("DisableLayer 3");
  sendCmd("Clear");
  sendCmd("FontSize 60");
  sendCmd("Color FFFFFF");
  cmd = "FillText 0 60 \""; cmd = cmd + cityName + "\"";
  sendCmd(cmd.c_str());
}

void printTemperature(String temperature)
{
  String cmd;
  sendCmd("Layer 4");
  sendCmd("DisableLayer 4");
  sendCmd("Clear");
  sendCmd("FontSize 100");
  sendCmd("Color FFFFFF");
  cmd = "FillText 0 90 \""; cmd = cmd + temperature + "℃\"";
  sendCmd(cmd.c_str());
}

void printHumidity(String humidity)
{
  String cmd;
  sendCmd("Layer 5");
  sendCmd("DisableLayer 5");
  sendCmd("Clear");
  sendCmd("FontSize 48");
  sendCmd("Color FFFFFF");
  cmd = "FillText 0 50 \""; cmd = cmd + humidity + "%\"";
  sendCmd(cmd.c_str());
}

void printIcon(String id)
{
  sendCmd("Layer 2");
  sendCmd("DisableLayer 2");
  sendCmd("Clear");
  
  String cmd, icon;
  char code = id.charAt(0);
  switch(code)
  {
    case '2':
    case '3':
    case '5':
      icon = "/image/weather5.png";
      break;
    case '6':
      icon = "/image/weather7.png";
      break;
    case '7':
      icon = "/image/weather2.png";
      break;
     case '8':
      if(id.equals("800"))
        icon = "/image/weather1.png";
      else if(id.equals("801"))
        icon = "/image/weather4.png";
      else if(id.equals("802"))
        icon = "/image/weather2.png";
      else if(id.equals("803"))
        icon = "/image/weather3.png";
      else if(id.equals("804"))
        icon = "/image/weather3.png";
      break;
  }

  cmd = "Image 0 0 \"" + icon + "\"";
  sendCmd(cmd.c_str());
}

void printWeather(String weather)
{
  String cmd;
  sendCmd("Layer 1");
  sendCmd("DisableLayer 1");
  sendCmd("Clear");
  sendCmd("FontSize 48");
  sendCmd("Color FFFFFF");
  weather.toUpperCase();
  cmd = "FillText 0 50 \""; cmd = cmd + weather + "\"";
  //sendCmd(cmd.c_str());
}

Comments

Similar projects you might like

Display Current Weather with Arduino and Python!

Project tutorial by Arduino “having11” Guy

  • 8,399 views
  • 4 comments
  • 19 respects

Rube Goldberg Weather Station with Internet Data Storage

Project in progress by randtekk

  • 9,407 views
  • 7 comments
  • 48 respects

MKR Zero Weather Data Logger

Project tutorial by Arduino_Genuino

  • 28,902 views
  • 18 comments
  • 59 respects

Getting Weather Data

by Officine Innesto

  • 10,369 views
  • 2 comments
  • 9 respects

Arduino Based Weather Station with Remote Sensor Unit

Project showcase by antiElectron

  • 11,882 views
  • 7 comments
  • 49 respects

Weather Station Based On Arduino And NodeMCU

Project tutorial by miklas

  • 6,822 views
  • 0 comments
  • 19 respects
Add projectSign up / Login