diff options
author | Erich Eckner <git@eckner.net> | 2020-02-07 14:42:40 +0100 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2020-02-07 14:42:40 +0100 |
commit | 4f52dda6e8795ff98ee6cb579f754219f66f41be (patch) | |
tree | 0e028501f4df77fcdd312dd0ae93d1ba16302de9 | |
parent | 1f40d334b2c39feb6dcc02ae31ae1a74fc4bc322 (diff) | |
download | anzeige-4f52dda6e8795ff98ee6cb579f754219f66f41be.tar.xz |
fully threaded, now
-rw-r--r-- | anzeige.c | 153 | ||||
-rw-r--r-- | anzeige.h | 16 | ||||
-rw-r--r-- | input_gadgets.c | 205 | ||||
-rw-r--r-- | input_gadgets.h | 21 |
4 files changed, 311 insertions, 84 deletions
@@ -1,17 +1,18 @@ #define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <unistd.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> +#include <netdb.h> #include <pthread.h> #include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> #include <time.h> -#include <netdb.h> +#include <unistd.h> +#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<THREAD_IDX_MAX; i++) + input_threads[i].keep_running = 1; - int i=0; + pthread_create(&input_threads[THREAD_IDX_WARNINGS].thread_id, NULL, gadgets_watch_weather_warnings, &input_threads[THREAD_IDX_WARNINGS]); + pthread_create(&input_threads[THREAD_IDX_OUTSIDE].thread_id, NULL, gadgets_watch_current_temperature, &input_threads[THREAD_IDX_OUTSIDE]); + pthread_create(&input_threads[THREAD_IDX_FORECAST].thread_id, NULL, gadgets_watch_weather_forecast, &input_threads[THREAD_IDX_FORECAST]); + pthread_create(&input_threads[THREAD_IDX_INSIDE].thread_id, NULL, gadgets_watch_humidity, &input_threads[THREAD_IDX_INSIDE]); + + scroll_data . shine_until = time(NULL) + 1000000; while (scroll_data . keep_running) { if (got_input()) { - next_update = 0; // update now! scroll_data . shine_until = time(NULL) + 60; + for (int i=0; i<THREAD_IDX_MAX; i++) + input_threads[i].force_update = 1; } - if ((time(NULL) >= 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<THREAD_IDX_MAX; i++) + if (input_threads[i].output_ready) { + if (strcmp(text_buffers[i], input_threads[i].text_output)) { + strcpy(text_buffers[i], input_threads[i].text_output); + updated = 1; + } + if (i == THREAD_IDX_OUTSIDE) { + if (outside_temperature != input_threads[i].double_output[0]) + outside_temperature = input_threads[i].double_output[0]; + if (outside_humidity != input_threads[i].double_output[1]) + outside_humidity = input_threads[i].double_output[1]; + } + if (i == THREAD_IDX_INSIDE) { + if (inside_temperature != input_threads[i].double_output[0]) + inside_temperature = input_threads[i].double_output[0]; + if (inside_humidity != input_threads[i].double_output[1]) + inside_humidity = input_threads[i].double_output[1]; + } + if (((i == THREAD_IDX_OUTSIDE) || (i == THREAD_IDX_INSIDE)) && + ((outside_temperature!=0) || (outside_humidity!=0)) && + ((inside_temperature!=0) || (inside_humidity!=0))) { + gadgets_calculate_humidity_level( + humidity_text_buffer, + MAX_TEXT_OUTPUT_LEN, + outside_temperature, + outside_humidity, + inside_temperature, + inside_humidity + ); + if (strcmp(text_buffers[THREAD_IDX_INSIDE], humidity_text_buffer)) { + strcpy(text_buffers[THREAD_IDX_INSIDE], humidity_text_buffer); + updated = 1; + } + } + input_threads[i].output_ready = 0; + } + if (updated) { + updated = 0; memset(text_buffer, 0, TEXT_BUFFER_LENGTH); text_buffer_end = text_buffer; - double temperature, humidity; - - text_buffer_end = gadgets_retrieve_weather_warnings(text_buffer_end,text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end); - if (text_buffer_end == NULL) { - fprintf(stderr, "gadgets_retrieve_weather_warnings 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_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<OUTPUT_IDX_MAX; i++) { + if ((text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end > 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<THREAD_IDX_MAX; i++) + input_threads[i].keep_running = 0; + free(text_buffer); pthread_join(scroll_data . thread_id, NULL); turn_off_display(); + for (int i=0; i<THREAD_IDX_MAX; i++) + pthread_join(input_threads[i].thread_id, NULL); + return EXIT_SUCCESS; } // main @@ -201,7 +229,8 @@ void handle_signals(int signo) scroll_data . keep_running = 0; break; case SIGUSR1: - next_update = 0; + for (int i=0; i<THREAD_IDX_MAX; i++) + input_threads[i] . force_update = 1; scroll_data . shine_until = time(NULL) + 60; break; } diff --git a/anzeige.h b/anzeige.h new file mode 100644 index 0000000..ea6b6c0 --- /dev/null +++ b/anzeige.h @@ -0,0 +1,16 @@ +#ifndef ANZEIGE_H +#define ANZEIGE_H + +#define OUTPUT_IDX_WARNINGS 0 +#define OUTPUT_IDX_OUTSIDE 1 +#define OUTPUT_IDX_FORECAST 2 +#define OUTPUT_IDX_INSIDE 3 +#define OUTPUT_IDX_MAX 4 + +#define THREAD_IDX_WARNINGS 0 +#define THREAD_IDX_OUTSIDE 1 +#define THREAD_IDX_FORECAST 2 +#define THREAD_IDX_INSIDE 3 +#define THREAD_IDX_MAX 4 + +#endif // ANZEIGE_H diff --git a/input_gadgets.c b/input_gadgets.c index 5c7376e..7121682 100644 --- a/input_gadgets.c +++ b/input_gadgets.c @@ -1,13 +1,16 @@ -#define _XOPEN_SOURCE -#include <string.h> -#include <stdlib.h> +#define _GNU_SOURCE + #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 <netdb.h> +#include <regex.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> #include <zip.h> #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; i<zip_get_num_entries(za, 0); i++) { zip_stat_index(za, i, 0, &zs); @@ -972,13 +1055,48 @@ char *gadgets_retrieve_weather_warnings(char *output, int max_len) return ende; } -char *gadgets_retrieve_humidity(char *output, int max_len, double fh_temperature, double fh_humidity) +void *gadgets_watch_weather_warnings(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_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 <pthread.h> +#include <stdint.h> + +#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 |