[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
Prześlij komentarz
Dzięki za komentarz!