summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Eckner <git@eckner.net>2020-02-07 14:42:40 +0100
committerErich Eckner <git@eckner.net>2020-02-07 14:42:40 +0100
commit4f52dda6e8795ff98ee6cb579f754219f66f41be (patch)
tree0e028501f4df77fcdd312dd0ae93d1ba16302de9
parent1f40d334b2c39feb6dcc02ae31ae1a74fc4bc322 (diff)
downloadanzeige-4f52dda6e8795ff98ee6cb579f754219f66f41be.tar.xz
fully threaded, now
-rw-r--r--anzeige.c153
-rw-r--r--anzeige.h16
-rw-r--r--input_gadgets.c205
-rw-r--r--input_gadgets.h21
4 files changed, 311 insertions, 84 deletions
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 <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