diff options
author | Erich Eckner <git@eckner.net> | 2018-10-24 15:30:09 +0200 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2018-10-24 15:30:09 +0200 |
commit | 49116c127443e5880423eca02889f8d576635652 (patch) | |
tree | 98d22f02766e84aa2290150557f54e4676591e87 | |
parent | d7e5888dd7467daf56b9b7adc52c28794cdc6282 (diff) | |
download | anzeige-49116c127443e5880423eca02889f8d576635652.tar.xz |
input_gadgets: gadgets_retrieve_weather_forecast() neu
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | anzeige.c | 2 | ||||
-rw-r--r-- | input_gadgets.c | 126 | ||||
-rw-r--r-- | input_gadgets.h | 1 |
4 files changed, 130 insertions, 3 deletions
@@ -1,13 +1,13 @@ CFLAGS="-Werror=implicit-function-declaration" anzeige: anzeige.c fonts.o input_gadgets.o multiplexer.o - gcc -O3 -o "$@" $(CFLAGS) -lpthread -lcurl $^ + gcc -O3 -o "$@" $(CFLAGS) -lpthread -lxml2 -lcurl $^ fonts.o: fonts.c fonts.h gcc -O3 -o "$@" $(CFLAGS) -c "$<" input_gadgets.o: input_gadgets.c input_gadgets.h - gcc -O3 -o "$@" $(CFLAGS) -c -lcurl "$<" + gcc -O3 -o "$@" $(CFLAGS) -c -I/usr/include/libxml2 -lxml2 -lcurl "$<" multiplexer.o: multiplexer.c multiplexer.h gcc -O3 -o "$@" $(CFLAGS) -c -lpthread "$<" @@ -51,7 +51,7 @@ int main(int argc, char **argv) } memset(text_buffer, 0, TEXT_BUFFER_LENGTH); - ret_val = gadgets_retrieve_current_temperature(text_buffer,TEXT_BUFFER_LENGTH); + ret_val = gadgets_retrieve_weather_forecast(text_buffer,TEXT_BUFFER_LENGTH); if (ret_val) { free(text_buffer); exit(ret_val); diff --git a/input_gadgets.c b/input_gadgets.c index f452ca0..0426c56 100644 --- a/input_gadgets.c +++ b/input_gadgets.c @@ -2,6 +2,11 @@ #include <stdlib.h> #include <curl/curl.h> #include <regex.h> +#include <stdio.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <time.h> +#include <math.h> #include "input_gadgets.h" @@ -92,3 +97,124 @@ int gadgets_retrieve_current_temperature(unsigned char *output, int max_len) free(chunk.memory); return 0; } + +xmlNode *xml_find_node_by_name(xmlNode *cur_node, char *name) +{ + while (cur_node) { + if ((cur_node -> type == XML_ELEMENT_NODE) && + (strcmp(cur_node -> name, name) == 0)) + return cur_node; + cur_node = cur_node -> next; + } + return NULL; +} + +int gadgets_retrieve_weather_forecast(unsigned char *output, int max_len) +{ + CURL *curl_handle; + CURLcode res; + struct MemoryStruct chunk; + int ret_val; + + chunk.memory = malloc(1); + chunk.size = 0; + + curl_global_init(CURL_GLOBAL_ALL); + + curl_handle = curl_easy_init(); + if (!curl_handle) { + perror("Failed to init curl"); + free(chunk.memory); + return EXIT_FAILURE; + } + curl_easy_setopt(curl_handle, CURLOPT_URL, "https://api.met.no/weatherapi/locationforecast/1.9/?lat=50.8830&lon=11.6223&msl=170"); + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + res = curl_easy_perform(curl_handle); + curl_easy_cleanup(curl_handle); + if (res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + free(chunk.memory); + return EXIT_FAILURE; + } + + LIBXML_TEST_VERSION + + xmlDocPtr doc; + doc = xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0); + free(chunk.memory); + if (doc == NULL) { + fprintf(stderr, "Failed to parse document\n"); + return EXIT_FAILURE; + } + + xmlNode *cur_node = NULL; + xmlNode *sub_node = NULL; + cur_node = xmlDocGetRootElement(doc); + if (!cur_node) { + fprintf(stderr, "Failed to reach root node of xml\n"); + return EXIT_FAILURE; + } + cur_node = xml_find_node_by_name(cur_node, "weatherdata"); + if (!cur_node) { + fprintf(stderr, "Failed to enter <weatherdata>\n"); + return EXIT_FAILURE; + } + cur_node = xml_find_node_by_name(cur_node -> children, "product"); + if (!cur_node) { + fprintf(stderr, "Failed to enter <product>\n"); + return EXIT_FAILURE; + } + + float rain_total = 0, temp_min = NAN, temp_max = NAN, wind_max = NAN, cur_val; + + char time_str[2][21]; + time_t now; + time(&now); + now = ((int)(now/60/60))*60*60; + + for (cur_node = cur_node -> children; cur_node; cur_node = cur_node->next) { + if ((cur_node->type == XML_ELEMENT_NODE) && (strcmp(cur_node->name,"time")==0) && (strcmp(xmlGetProp(cur_node,"datatype"),"forecast")==0)) { + for (int i=0; i<=14; i++) { + now += i*60*60; + strftime(time_str[0],21,"%Y-%m-%dT%H:%M:%SZ",gmtime(&now)); + now += 60*60; + strftime(time_str[1],21,"%Y-%m-%dT%H:%M:%SZ",gmtime(&now)); + now -= (i+1)*60*60; + if ((strcmp(time_str[1],xmlGetProp(cur_node,"from"))==0) && (strcmp(time_str[1],xmlGetProp(cur_node,"to"))==0)) { + sub_node = xml_find_node_by_name(cur_node -> children,"location"); + cur_val = atof(xmlGetProp(xml_find_node_by_name(sub_node -> children, "temperature"), "value")); + if (isnan(temp_max) || (cur_val > temp_max)) + temp_max = cur_val; + if (isnan(temp_min) || (cur_val < temp_min)) + temp_min = cur_val; + cur_val = atof(xmlGetProp(xml_find_node_by_name(sub_node -> children, "windSpeed"),"mps")); + if (isnan(wind_max) || (cur_val > wind_max)) + wind_max = cur_val; + } + if ((strcmp(time_str[0],xmlGetProp(cur_node,"from"))==0) && (strcmp(time_str[1],xmlGetProp(cur_node,"to"))==0)) { + sub_node = xml_find_node_by_name(cur_node -> children,"location"); + if (!sub_node) + continue; + sub_node = xml_find_node_by_name(sub_node -> children, "precipitation"); + if (!sub_node) + continue; + rain_total += atof(xmlGetProp(sub_node,"value")); + } + } + } + } + xmlFreeDoc(doc); + xmlCleanupParser(); + + int i = snprintf(output, max_len, "%0.1f ,, %0.1f °C; %0.1f mm; %0.1f m/s;", temp_min, temp_max, rain_total, wind_max); + for (; i>=0; i--) + if (output[i] == '.') + output[i] = ','; + else if (output[i] == ',') + output[i] = '.'; + + return EXIT_SUCCESS; +} diff --git a/input_gadgets.h b/input_gadgets.h index cdf1bcb..002d9ef 100644 --- a/input_gadgets.h +++ b/input_gadgets.h @@ -4,3 +4,4 @@ struct MemoryStruct { }; int gadgets_retrieve_current_temperature(unsigned char *output, int max_len); +int gadgets_retrieve_weather_forecast(unsigned char *output, int max_len); |