[C++] Piszemy aplikację pogodową, część 3

W części trzeciej tej serii zostanie utworzony kod programu odpowiadający za pobieranie danych pogodowych z serwisu OpenWeather oraz parsowanie pobranego ciągu JSON.

Plik data.hpp

W pliku data.hpp zadeklarujemy strukturę Weather oraz klasę Data:

#ifndef DATA_HPP
#define DATA_HPP

#include <iostream>

using namespace std;

struct memory {
 
 char *response;
 size_t size;
 
};

struct Weather {
 
 string location;
 string conditions;
 int temperature;
 int pressure;
 int wind_speed;
 const char* wind_direction;
 int humidity;
 int memory;
 string error;
 
};

class Data {

public:
 
 static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp);

public:
 
 memory get(string location);
 
 Weather set(char* input_location);
 
};

#endif

Plik data.cpp

W pliku data.cpp tworzymy logikę metod klasy Data. Jak wspomniałem na początku wpisu, kod ten będzie odpowiedzialny za pobieranie danych oraz za parsowanie ciągu JSON. W związku z tym do tego pliku musimy dołączyć bibliotekę CURL do obsługi żądań HTTP oraz bibliotekę nlohmann/json do przetwarzania danych w formacie JSON:

#include "data.hpp"
#include <string.h>
#include "config.hpp"
#include <curl/curl.h>
#include "json.hpp"

using json = nlohmann::json;

size_t Data::write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
 
 size_t realsize = size * nmemb;
 struct memory *mem = (struct memory *)userp;
 
 char *ptr = static_cast<char*>(realloc(mem->response, mem->size + realsize + 1));
 
 if(ptr == NULL) {
  
  return 0;
  
 }
 
 mem->response = ptr;
 memcpy(&(mem->response[mem->size]), contents, realsize);
 mem->size += realsize;
 mem->response[mem->size] = 0;
 
 return realsize;
 
}

memory Data::get(string location) {
 
 Config config;
 
 CURL *curl_handle;
 CURLcode res;
 
 struct memory chunk;
 
 chunk.response = (char*)malloc(1);
 chunk.size = 0;
 
 curl_global_init(CURL_GLOBAL_DEFAULT);
 curl_handle = curl_easy_init();
 
 string data_url = config.get_option("weather_data_url") + location;
 
 curl_easy_setopt(curl_handle, CURLOPT_URL, data_url.c_str());
 
 #ifdef SKIP_PEER_VERIFICATION
 
 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
 
 #endif
 
 #ifdef SKIP_HOSTNAME_VERIFICATION
 
 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
 
 #endif
 
 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:77.0) Gecko/20190101 Firefox/77.0");
 
 res = curl_easy_perform(curl_handle);
 
 if(res != CURLE_OK) {
  
  fprintf(stderr, "Error: %s\n", curl_easy_strerror(res));
  
 }
 
 return chunk;
 
 curl_easy_cleanup(curl_handle);
 
 free(chunk.response);
 
 curl_global_cleanup();
 
 return chunk;
 
}

Weather Data::set(char* input_location) {
 
 memory chunk;
 
 chunk = get(input_location);
 
 string weather_json = string(chunk.response);
 
 Weather weather_data;
 
 weather_data.error = "";
 
 try {
  
  auto data = json::parse(weather_json);
  
  if(data["cod"] == 200) {
   
   weather_data.location = data["name"];
   weather_data.conditions = data["weather"][0]["description"];
   weather_data.temperature = round(( float ) data["main"]["temp"]);
   weather_data.pressure = data["main"]["pressure"];
   
   int deg;
   deg = data.value("deg", 0);
   const char* xx[16] {"↓", "NNE", "↙", "ENE", "←", "ESE", "↖", "SSE", "↑", "SSW", "↗", "WSW", "→", "WNW", "↘", "NNW"};
   int index = fmod(((( int ) deg + 11) / 22.5), 16);
   
   weather_data.wind_speed = round(( float ) data["wind"]["speed"] * 1.852);
   weather_data.wind_direction = xx[index];
   
   weather_data.humidity = data["main"]["humidity"];
   weather_data.memory = chunk.size;
   
   return weather_data;
   
  }
  
  else {
   
   weather_data.error = "Brak danych dla podanej lokalizacji!";
   
   return weather_data;
   
  }
  
 }
 
 catch(json::parse_error& e) {
  
  weather_data.error = e.what();
  
  return weather_data;
  
 }
 
}

Komentarze

Popular

[HTML] Jak wstawić obrazek?

[C++] Jak obliczyć pole i obwód trapezu?

[PHP] Jak pobrać adres strony?