From 4f52dda6e8795ff98ee6cb579f754219f66f41be Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Fri, 7 Feb 2020 14:42:40 +0100 Subject: fully threaded, now --- anzeige.c | 153 +++++++++++++++++++++++++----------------- anzeige.h | 16 +++++ input_gadgets.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++----- input_gadgets.h | 21 ++++-- 4 files changed, 311 insertions(+), 84 deletions(-) create mode 100644 anzeige.h diff --git a/anzeige.c b/anzeige.c index a1ad81f..1beb796 100644 --- a/anzeige.c +++ b/anzeige.c @@ -1,17 +1,18 @@ #define _GNU_SOURCE -#include -#include -#include -#include -#include #include -#include +#include +#include #include #include +#include +#include +#include +#include #include -#include +#include +#include "anzeige.h" #include "fonts.h" #include "input_gadgets.h" #include "multiplexer.h" @@ -20,15 +21,14 @@ void drop_privileges(); void handle_signals(int signo); t_scroll_data scroll_data; -time_t next_update = 0; -time_t next_dns_query = 0; +t_input_thread input_threads[THREAD_IDX_MAX]; int main(int argc, char **argv) { int ret_val; - #define TEXT_BUFFER_LENGTH SCROLL_BUF_LEN / 5 - char *text_buffer; - char *text_buffer_end; + + memset(&scroll_data, 0, sizeof(t_scroll_data)); + memset(&input_threads, 0, sizeof(t_input_thread) * THREAD_IDX_MAX); // Set up gpi pointer for direct register access ret_val = multiplexer_setup_root(); @@ -64,69 +64,98 @@ int main(int argc, char **argv) // configure the gpio pins and start the multiplexer thread multiplexer_setup_scroll(&scroll_data); + #define TEXT_BUFFER_LENGTH SCROLL_BUF_LEN / 5 + char *text_buffer; + char *text_buffer_end; + char text_buffers[OUTPUT_IDX_MAX][MAX_TEXT_OUTPUT_LEN]; + char humidity_text_buffer[MAX_TEXT_OUTPUT_LEN]; + double outside_temperature = 0, outside_humidity = 0, inside_temperature = 0, inside_humidity = 0; + int updated = 0; + + memset(humidity_text_buffer, 0 ,MAX_TEXT_OUTPUT_LEN); text_buffer = malloc(TEXT_BUFFER_LENGTH); if (text_buffer == NULL) { fprintf(stderr, "malloc failed to allocate %d bytes\n", TEXT_BUFFER_LENGTH); turn_off_display(); return EXIT_FAILURE; } + memset(text_buffer, 0, TEXT_BUFFER_LENGTH); + memset(text_buffers, 0, OUTPUT_IDX_MAX * MAX_TEXT_OUTPUT_LEN); - scroll_data . shine_until = time(NULL) + 10; + for (int i=0; i= next_update) && (scroll_data . update == 0)) { - next_update = time(NULL) + 600; // 10 minutes ahead - next_dns_query = time(NULL) + 30; // 1/2 minute ahead + for (int i=0; i 0) - text_buffer_end += snprintf(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "; "); - text_buffer_end = gadgets_retrieve_current_temperature(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, &temperature, &humidity); - if (text_buffer_end == NULL) { - fprintf(stderr, "gadgets_retrieve_current_temperature failed\n"); - free(text_buffer); - turn_off_display(); - return EXIT_FAILURE; - } - if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end > 0) - text_buffer_end += snprintf(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "; "); - text_buffer_end = gadgets_retrieve_weather_forecast(text_buffer_end,text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end); - if (text_buffer_end == NULL) { - fprintf(stderr, "gadgets_retrieve_weather_forecast failed\n"); - free(text_buffer); - turn_off_display(); - return EXIT_FAILURE; - } - if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end > 0) - text_buffer_end += snprintf(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "; "); - text_buffer_end = gadgets_retrieve_humidity(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, temperature, humidity); - if (text_buffer_end == NULL) { - fprintf(stderr, "gadgets_retrieve_humidity failed\n"); - free(text_buffer); - turn_off_display(); - return EXIT_FAILURE; + for (int i=0; i 0) && (*text_buffers[i])) + text_buffer_end += snprintf( + text_buffer_end, + text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, + "%s; ", + text_buffers[i] + ); } + struct tm time_struct; + time_t now; memset(&time_struct, 0, sizeof(time_struct)); - localtime_r(&next_update, &time_struct); + now = time(NULL); + localtime_r(&now, &time_struct); for (int i = 0; i < (time_struct . tm_wday + 6) % 7 + 1; i++) { if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end <= 0) break; @@ -151,21 +180,20 @@ int main(int argc, char **argv) ); scroll_data . update = 1; } - if (time(NULL) >= next_dns_query) { - next_dns_query = time(NULL) + 30; // 1/2 minute ahead - gethostbyname("wetter.mb.fh-jena.de"); - gethostbyname("api.met.no"); - gethostbyname("opendata.dwd.de"); - gethostbyname("kpi.ddns.eckner.net"); - } usleep(100000); } + for (int i=0; i -#include +#define _GNU_SOURCE + #include -#include -#include #include #include -#include #include +#include +#include +#include +#include +#include +#include +#include #include #include "input_gadgets.h" @@ -230,6 +233,49 @@ char *gadgets_retrieve_current_temperature(char *output, int max_len, double *te return ende; } +void *gadgets_watch_current_temperature(void *param) +{ + t_input_thread *p = param; + time_t next_update = 0; + time_t next_dns_query = 0; + p->text_output = malloc(MAX_TEXT_OUTPUT_LEN); + p->double_output = malloc(sizeof(double)*2); + if ((p->text_output == NULL) || (p->double_output == NULL)) { + fprintf(stderr, "malloc failed\n"); + return NULL; + } + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + memset(p->double_output, 0, sizeof(double)*2); + while (p->keep_running) { + if (((time(NULL) >= next_update) || (p->force_update)) && (!p->output_ready)) { + next_update = time(NULL) + 600; // 10 minutes ahead + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + if (!gadgets_retrieve_current_temperature( + p->text_output, + MAX_TEXT_OUTPUT_LEN-1, + &p->double_output[0], + &p->double_output[1] + )) { + fprintf(stderr, "gadgets_retrieve_current_temperature failed\n"); + snprintf(p->text_output, MAX_TEXT_OUTPUT_LEN, "gadgets_retrieve_current_temperature failed"); + p->double_output[0] = 0; + p->double_output[1] = 0; + } + p->force_update = 0; + p->output_ready = 1; + } + if (time(NULL) >= next_dns_query) { + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + gethostbyname("wetter.mb.fh-jena.de"); + } + usleep(100000); + } + free(p->text_output); + free(p->double_output); + return NULL; +} + xmlNode *xml_find_node_by_name(xmlNode *cur_node, char *name) { while (cur_node) { @@ -394,6 +440,42 @@ char *gadgets_retrieve_weather_forecast(char *output, int max_len) return output; } +void *gadgets_watch_weather_forecast(void *param) +{ + t_input_thread *p = param; + time_t next_update = 0; + time_t next_dns_query = 0; + p->text_output = malloc(MAX_TEXT_OUTPUT_LEN); + if (p->text_output == NULL) { + fprintf(stderr, "malloc failed\n"); + return NULL; + } + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + while (p->keep_running) { + if (((time(NULL) >= next_update) || (p->force_update)) && (!p->output_ready)) { + next_update = time(NULL) + 600; // 10 minutes ahead + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + if (!gadgets_retrieve_weather_forecast( + p->text_output, + MAX_TEXT_OUTPUT_LEN-1 + )) { + fprintf(stderr, "gadgets_retrieve_weather_forecast failed\n"); + snprintf(p->text_output, MAX_TEXT_OUTPUT_LEN, "gadgets_retrieve_weather_forecast failed"); + } + p->force_update = 0; + p->output_ready = 1; + } + if (time(NULL) >= next_dns_query) { + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + gethostbyname("api.met.no"); + } + usleep(100000); + } + free(p->text_output); + return NULL; +} + char *gadgets_retrieve_weather_warnings(char *output, int max_len) { CURL *curl_handle; @@ -484,6 +566,7 @@ char *gadgets_retrieve_weather_warnings(char *output, int max_len) free(chunk.memory); return NULL; } + memset(warnings, 0, sizeof(warning_t)); for (int i=0; itext_output = malloc(MAX_TEXT_OUTPUT_LEN); + if (p->text_output == NULL) { + fprintf(stderr, "malloc failed\n"); + return NULL; + } + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + while (p->keep_running) { + if (((time(NULL) >= next_update) || (p->force_update)) && (!p->output_ready)) { + next_update = time(NULL) + 600; // 10 minutes ahead + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + if (!gadgets_retrieve_weather_warnings( + p->text_output, + MAX_TEXT_OUTPUT_LEN-1 + )) { + fprintf(stderr, "gadgets_retrieve_weather_warnings failed\n"); + snprintf(p->text_output, MAX_TEXT_OUTPUT_LEN, "gadgets_retrieve_weather_warnings failed"); + } + p->force_update = 0; + p->output_ready = 1; + } + if (time(NULL) >= next_dns_query) { + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + gethostbyname("opendata.dwd.de"); + } + usleep(100000); + } + free(p->text_output); + return NULL; +} + +char *gadgets_retrieve_humidity(char *output, int max_len, double *temperature, double *humidity) { CURL *curl_handle; CURLcode res; MemoryStruct chunk; int ret_val; - double temperature, humidity; char *ende = output; chunk.memory = malloc(1); @@ -1034,20 +1152,29 @@ char *gadgets_retrieve_humidity(char *output, int max_len, double fh_temperature char tmp_str[12]; snprintf(tmp_str, 11, "%.*s", (int)(rm[1].rm_eo - rm[1].rm_so), (char*)(chunk.memory + rm[1].rm_so)); - humidity = atof(tmp_str) / 100.; + *humidity = atof(tmp_str) / 100.; snprintf(tmp_str, 11, "%.*s", (int)(rm[2].rm_eo - rm[2].rm_so), (char*)(chunk.memory + rm[2].rm_so)); - temperature = atof(tmp_str); + *temperature = atof(tmp_str); + free(chunk.memory); - humidity *= maximale_luftfeuchte(temperature); - fh_humidity *= maximale_luftfeuchte(fh_temperature); + return ende; +} - if ((output + max_len - ende > 0) && (temperature <= taupunkt(fh_humidity)+2)) - ende += snprintf(ende, max_len, "!TPa %.1f K; ", taupunkt(fh_humidity) - temperature); - if ((output + max_len - ende > 0) && (temperature <= taupunkt(humidity)+2)) - ende += snprintf(ende, max_len, "!TPi %.1f K; ", taupunkt(humidity) - temperature); +char *gadgets_calculate_humidity_level(char *output, int max_len, double outside_temperature, double outside_humidity, double inside_temperature, double inside_humidity) +{ + char *ende; + + ende = output; + + inside_humidity *= maximale_luftfeuchte(inside_temperature); + outside_humidity *= maximale_luftfeuchte(outside_temperature); + + if ((output + max_len - ende > 0) && (inside_temperature <= taupunkt(outside_humidity)+2)) + ende += snprintf(ende, max_len, "!TPa %.1f K; ", taupunkt(outside_humidity) - inside_temperature); + if ((output + max_len - ende > 0) && (inside_temperature <= taupunkt(inside_humidity)+2)) + ende += snprintf(ende, max_len, "!TPi %.1f K; ", taupunkt(inside_humidity) - inside_temperature); if (output + max_len - ende > 0) - ende += snprintf(ende, max_len, "%.0f %%", humidity * 100 / fh_humidity); - free(chunk.memory); + ende += snprintf(ende, max_len, "%.0f %%", inside_humidity * 100 / outside_humidity); while (output < ende) { if (*output == '.') @@ -1057,3 +1184,45 @@ char *gadgets_retrieve_humidity(char *output, int max_len, double fh_temperature return ende; } + +void *gadgets_watch_humidity(void *param) +{ + t_input_thread *p = param; + time_t next_update = 0; + time_t next_dns_query = 0; + p->text_output = malloc(MAX_TEXT_OUTPUT_LEN); + p->double_output = malloc(sizeof(double)*2); + if ((p->text_output == NULL) || (p->double_output == NULL)) { + fprintf(stderr, "malloc failed\n"); + return NULL; + } + memset(p->text_output, 0, MAX_TEXT_OUTPUT_LEN); + memset(p->double_output, 0, sizeof(double)*2); + while (p->keep_running) { + if (((time(NULL) >= next_update) || (p->force_update)) && (!p->output_ready)) { + next_update = time(NULL) + 600; // 10 minutes ahead + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + if (!gadgets_retrieve_humidity( + p->text_output, + MAX_TEXT_OUTPUT_LEN-1, + &p->double_output[0], + &p->double_output[1] + )) { + fprintf(stderr, "gadgets_retrieve_humidity failed\n"); + snprintf(p->text_output, MAX_TEXT_OUTPUT_LEN, "gadgets_retrieve_humidity failed\n"); + p->double_output[0]=0; + p->double_output[1]=0; + } + p->force_update = 0; + p->output_ready = 1; + } + if (time(NULL) >= next_dns_query) { + next_dns_query = time(NULL) + 30; // 1/2 minute ahead + gethostbyname("kpi.ddns.eckner.net"); + } + usleep(100000); + } + free(p->text_output); + free(p->double_output); + return NULL; +} diff --git a/input_gadgets.h b/input_gadgets.h index b3e3644..6f22056 100644 --- a/input_gadgets.h +++ b/input_gadgets.h @@ -1,6 +1,11 @@ #ifndef INPUT_GADGETS_H #define INPUT_GADGETS_H +#include +#include + +#define MAX_TEXT_OUTPUT_LEN 256 + typedef struct { char *memory; size_t size; @@ -15,9 +20,17 @@ typedef struct { time_t onset, expires; } warning_t; -char *gadgets_retrieve_current_temperature(char *output, int max_len, double *temperature, double *humidity); -char *gadgets_retrieve_weather_forecast(char *output, int max_len); -char *gadgets_retrieve_weather_warnings(char *output, int max_len); -char *gadgets_retrieve_humidity(char *output, int max_len, double fh_temperature, double fh_humidity); +typedef struct { + pthread_t thread_id; + char *text_output; + double *double_output; + int output_ready, force_update, keep_running; +} t_input_thread; + +void *gadgets_watch_current_temperature(void *param); +void *gadgets_watch_weather_forecast(void *param); +void *gadgets_watch_weather_warnings(void *param); +void *gadgets_watch_humidity(void *param); +char *gadgets_calculate_humidity_level(char *output, int max_len, double outside_temperature, double outside_humidity, double inside_temperature, double inside_humidity); #endif // INPUT_GADGETS_H -- cgit v1.2.3-54-g00ecf