commenting

git-svn-id: file:///home/jan/tmp/wetterstation/trunk@103 dd492736-c11a-0410-ad51-8c26713eaf7f
This commit is contained in:
losinshi 2006-09-17 23:39:09 +00:00
parent 0b1912639b
commit 738cf5ff26
16 changed files with 422 additions and 158 deletions

View File

@ -26,46 +26,51 @@
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include "definitions.h"
#include "config.h"
#include "chart.h"
#include "common.h"
#include "image_file/image_file.h"
static int walk_image_cfg_list();
static void wait_for_childs();
config global_opts;
static int walk_image_cfg_list(); /* Definition fuer walk_image_cfg_list */
static void wait_for_childs(); /* Definition fuer wait_for_childs */
config global_opts; /* Globale Optionen */
/* Geht die Bilder-Configs durch und startet das
* Generieren der Bilder
* Rueckgabe: Anzahl der Childs die Geforkt wurden */
static int walk_image_cfg_list(){
int has_forked = 0;
pid_t pid = 0;
image_cfg_list_ptr tmp_ptr = global_opts.image_cfg;
int has_forked = 0; /* Zaehler der Childs */
pid_t pid = 0; /* Temporaer abgespeicherte Pid */
image_cfg_list_ptr tmp_ptr = global_opts.image_cfg; /* Hilfszeiger auf das aktuelle element der Config-Liste */
for(; tmp_ptr; tmp_ptr = tmp_ptr->next){
if(global_opts.fork){
if((pid = fork()) == 0){
clear_clean();
process_image_cfg(tmp_ptr->image_cfg_file);
exit(EXIT_SUCCESS);
for(; tmp_ptr; tmp_ptr = tmp_ptr->next){ /* Configliste durchgehen */
if(global_opts.fork){ /* Wenn geforkt werden soll */
if((pid = fork()) == 0){ /* Unterscheidung ob im Child oder im Parent */
clear_clean(); /* Wenn im Child, dann die Clean-Liste leeren */
process_image_cfg(tmp_ptr->image_cfg_file); /* Bild generieren */
exit(EXIT_SUCCESS); /* und Child beenden */
}
else if (pid == -1){
else if (pid == -1){ /* Probleme beim Fork */
exit_error(ERROR_FORK);
}
if(!has_forked){
if(!has_forked){ /* beim ersten durchlauf die warte-funktion an die Clean-Liste anhaengen */
add_clean(wait_for_childs, NULL);
}
has_forked++;
has_forked++; /* Den fork-zaehler erhoehen */
DEBUGOUT2("Prozess %d angelegt\n",pid);
} else {
process_image_cfg(tmp_ptr->image_cfg_file);
} else { /* Wenn nicht geforkt werden soll */
process_image_cfg(tmp_ptr->image_cfg_file); /* dann so das Bild generieren */
}
}
return has_forked;
}
/* Wartet auf gestartete Child-Prozesse */
static void wait_for_childs(void *dummy){
int ret_val;
pid_t pid;
@ -74,7 +79,10 @@ static void wait_for_childs(void *dummy){
}
}
/* Main - Funktion */
int main(int argc, char *argv[]){
DEBUGOUT1("Programm gestartet\n");
if(signal(SIGABRT, exit_sig_handler) == SIG_ERR)
@ -90,6 +98,7 @@ int main(int argc, char *argv[]){
exit_error(ERROR_SEIINST);
DEBUGOUT1("Signalhandler zum beenden per SIGTERM installiert\n");
/* Haupt-Config einlesen */
read_config(DEFAULT_CONFIG_FILE, 1, NULL);
/* Debug-Ausgaben, um zu sehen, ob die Optionen richtig gesetzt werden */
@ -104,6 +113,7 @@ int main(int argc, char *argv[]){
DEBUGOUT2(" Datenbank = %s\n",global_opts.pg_database);
DEBUGOUT2(" Timeout = %s\n",global_opts.pg_database);
/* Bilder - Configs durchgehen */
if(walk_image_cfg_list())
wait_for_childs(NULL);

View File

@ -56,6 +56,7 @@ void add_clean(clean_func_t func, void *data){
}
}
/* Zuletzt angefuegtes Clean - Element entfernen */
void remove_clean(){
clean_struct_ptr temp = clean_ptr;
if (temp != NULL){
@ -64,6 +65,7 @@ void remove_clean(){
}
}
/* Clean - Liste leeren */
void clear_clean(){
while(clean_ptr != NULL){
remove_clean();

View File

@ -22,12 +22,14 @@
#include "definitions.h"
/* Liste der Bilder - Configs */
typedef struct image_cfg_list_t *image_cfg_list_ptr;
typedef struct image_cfg_list_t {
char *image_cfg_file;
image_cfg_list_ptr next;
} image_cfg_list;
/* Globale Config */
typedef struct config_t {
char *pg_host;
char *pg_database;
@ -40,8 +42,11 @@ typedef struct config_t {
int fork;
} config;
/* Prototyp einer Finktion, die addclean() uebergeben
* wird. */
typedef void (*clean_func_t)(void *data);
/* Clean - Liste */
typedef struct clean_struct *clean_struct_ptr;
typedef struct clean_struct {
void *data;
@ -50,7 +55,7 @@ typedef struct clean_struct {
} clean_data;
/* Globale Optionen */
extern config global_opts;
/* Funktionen -------------------------------------------------------------*/
@ -65,7 +70,7 @@ void exit_sig_handler(int);
/* Eine (neuste) Clean-Funktion entfernen */
void remove_clean();
/* Eine Clean-Funktion hinzufügen */
/* Eine Clean-Funktion hinzufuegen */
void add_clean(clean_func_t , void *);
/* Alle clean-Funktionen entfernen */

View File

@ -38,7 +38,7 @@
static int add_image_cfg(const char *, void *);
/* Zuordnung zwischen Schlüsselwörtern in der Config, Der Funktion, die diese auswertet
/* Zuordnung zwischen Schluesselwoertern in der Config, Der Funktion, die diese auswertet
* und dem eld in der Options-Struktur */
static const config_keyword dflt_keywords[] = {
/* keyword handler variable address default */
@ -126,7 +126,7 @@ int read_config(char *file, int reset, const config_keyword *keywords){
if(keywords == NULL)
keywords = (config_keyword *)dflt_keywords;
/* Optionen mit default-werten füllen */
/* Optionen mit default-werten fuellen */
if(reset){
for (i = 0; keywords[i].keyword[0]; i++)
//printf("keyword: %s \n",keywords[i].keyword);
@ -134,9 +134,9 @@ int read_config(char *file, int reset, const config_keyword *keywords){
keywords[i].handler(keywords[i].def, keywords[i].var);
}
/* config-file öffnen */
/* config-file oeffnen */
if (!(in = fopen(file, "r"))) {
DEBUGOUT2("Kann Config-File: '%s' nicht öffnen!\n", file);
DEBUGOUT2("Kann Config-File: '%s' nicht oeffnen!\n", file);
return 0;
}
@ -144,10 +144,10 @@ int read_config(char *file, int reset, const config_keyword *keywords){
while (fgets(buffer, CONFIG_BUFFERSIZE, in)) {
lm++;
/* Zeilenvorschübe gegen null-terminierungs-Zeichen ersetzen */
/* Zeilenvorschuebe gegen null-terminierungs-Zeichen ersetzen */
if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
/* Originlzeile für eventuelle log-, bzw. debug-meldungen */
/* Originlzeile fuer eventuelle log-, bzw. debug-meldungen */
strcpy(orig, buffer);
/* Kommentazeichen gegen null-terminierungs-Zeichen ersetzen und damit alles dahinter ignorieren */

View File

@ -35,6 +35,6 @@ typedef struct config_keyword_t {
int read_config(char *, int , const config_keyword *);
/* Config-Zeilen auswerten */
int read_str(const char *, void *);
int read_int(const char *, void *);
int read_yn(const char *, void *);
int read_str(const char *, void *); /* Einen String lesen */
int read_int(const char *, void *); /* Einen int lesen */
int read_yn(const char *, void *); /* Ein yes/no in 1/0 umwandeln */

View File

@ -49,6 +49,7 @@
#define DEFAULT_X_FORMAT "%H:%M"
#define DEFAULT_X_FORMAT_EXTRA "%d.%m.%y| %H:%M"
/* Image-Default-Farben ---------------------------------------------- */
#define DEFAULT_BG_COLOR "DF:DF:EF:00"
#define DEFAULT_DIA_BG_COLOR "F0:A0:D0:D0"
#define DEFAULT_ZERO_LINE_COLOR "BF:80:80:40"
@ -65,20 +66,20 @@
/*Alle möglichen Definitionen, die in allen code-schnipseln benötigt werden*/
/*Alle moeglichen Definitionen, die in allen code-schnipseln benoetigt werden*/
/* Fehlermeldungen ------------------------------------------------------*/
#define ERROR_SEIINST "Signal-Fehler: Kann Signalhandler zum beenden nicht installieren\n"
#define ERROR_FORK "Fork-Fehler: Kann keinen neuen Prozess anlegen\n"
#define ERROR_STAT "Kann Stat nicht ausführen\n"
#define ERROR_STAT "Kann Stat nicht ausfuehren\n"
#define ERROR_MAKECONN "PgSQL-Fehler: Kann Datenbankverbindung nicht herstellen\n"
#define ERROR_QUERY "PgSQL-Fehler: Kann query nicht sudführen \n"
#define ERROR_QUERY "PgSQL-Fehler: Kann query nicht ausfuehren \n"
/* Puffergrößen -------------------------------------------------------- */
#define CONFIG_BUFFERSIZE 512 /* Größe des Puffers zum Config-einlesen */
#define QUERY_BUFFERSIZE 512 /* Größe des Zeichenpuffers für SQL-Anfragen */
/* Puffergroeßen -------------------------------------------------------- */
#define CONFIG_BUFFERSIZE 512 /* Groeße des Puffers zum Config-einlesen */
#define QUERY_BUFFERSIZE 512 /* Groeße des Zeichenpuffers fuer SQL-Anfragen */
/* Verschiedenes ------------------------------------------------------- */

View File

@ -1,2 +1,23 @@
/*
chart.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "image_common.h"

View File

@ -1,34 +1,60 @@
/*
image_common.h -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Repraesentiert eine Farbe */
typedef struct img_color *img_color_ptr;
typedef struct img_color {
int r;
int g;
int b;
int alpha;
int r; /* Rotanteil */
int g; /* Gruenanteil */
int b; /* Blauanteil */
int alpha; /* Alphawert */
} img_color_t;
typedef struct image_cfg {
char *file_name;
char *headline;
char *table_field;
int manual_table;
char *table_name;
long gen_interval;
long show_interval;
long label_interval;
int label_sum;
int width;
int height;
char *unit;
char *x_desc;
char *y_desc;
int sens_id;
double val_koeff;
char *x_fmt_extra;
char *x_fmt;
int zero_min;
int bars;
int dflt_dir;
/* Config eines Bildes */
typedef struct image_cfg {
char *file_name; /* Filename des Bildes */
char *headline; /* Ueberschrift */
char *table_field; /* Feldname in der Tabelle */
int manual_table; /* Tabelle manuell angeben */
char *table_name; /* manueller Tabellenname */
long gen_interval; /* Generierungsinterval */
long show_interval; /* Anzeigeinterval */
long label_interval; /* Label - Interval */
int label_sum; /* Sollen Werte aufsummiert statt gemittelt werden */
int width; /* Breite */
int height; /* Hoehe */
char *unit; /* Einheit, die an die Skala angehangen werden soll */
char *x_desc; /* Beschreibung der X - Achse */
char *y_desc; /* Beschreibung der Y - Achse */
int sens_id; /* Id des Sensors */
double val_koeff; /* Faktir mit dem die Werte multipliziert werden sollen */
char *x_fmt_extra; /* Formatstring fuer die erste und letzte Zeit */
char *x_fmt; /* Formatstring fuer die restlichen Labels */
int zero_min; /* Nullinie auf jeden Fall anzeigen */
int bars; /* Balken malen statt einer Linie */
int dflt_dir; /* Standart - Verzeichnis fuer die Bilder */
/* Farben */
img_color_ptr bg_color;
img_color_ptr dia_bg_color;
img_color_ptr dia_line_color;
@ -42,8 +68,7 @@ typedef struct image_cfg {
img_color_ptr label_y_color;
img_color_ptr desc_x_color;
img_color_ptr desc_y_color;
} image_cfg_t;
/* Entfaelt die aktuelle Bild - Config */
extern image_cfg_t img_cfg;

View File

@ -1,6 +1,6 @@
/*
chart.c -- Part of Chart-generator for the weatherstation
image_config.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
@ -29,6 +29,8 @@
#define BUFFSIZE 512
/* Funktionsdefinitionen */
static int read_time(const char *, void *);
static int read_color(const char *, void *);
static int read_double(const char *, void *);
@ -36,7 +38,7 @@ static int read_fmt_str(const char *, void *);
/* Zuordnung zwischen Schlüsselwörtern in der Config, Der Funktion, die diese auswertet
/* Zuordnung zwischen Schluesselwoertern in der Config, Der Funktion, die diese auswertet
* und dem eld in der Options-Struktur */
static const config_keyword keywords[] = {
/* keyword handler variable address default */
@ -54,8 +56,8 @@ static const config_keyword keywords[] = {
{"height", read_int, &(img_cfg.height), DEFAULT_HEIGHT},
{"unit", read_str, &(img_cfg.unit), DEFAULT_UNIT},
{"sensor_id", read_int, &(img_cfg.sens_id), DEFAULT_SENS_ID},
{"zero_min", read_yn, &(img_cfg.zero_min), DEFAULT_ZERO_MIN},
{"as_bars", read_yn, &(img_cfg.bars), DEFAULT_AS_BARS},
{"zero_min", read_yn, &(img_cfg.zero_min), DEFAULT_ZERO_MIN},
{"as_bars", read_yn, &(img_cfg.bars), DEFAULT_AS_BARS},
{"x_axis_desc", read_str, &(img_cfg.x_desc), DEFAULT_X_AX_DESC},
{"y_axis_desc", read_str, &(img_cfg.y_desc), DEFAULT_Y_AX_DESC},
{"x_format", read_fmt_str, &(img_cfg.x_fmt), DEFAULT_X_FORMAT},
@ -80,6 +82,8 @@ static const config_keyword keywords[] = {
{"", NULL, NULL, ""}
};
/* Einen Zeit - Format - String lesen */
static int read_fmt_str(const char *line, void *arg){
char **dest = arg;
char *new_line = NULL;
@ -90,13 +94,13 @@ static int read_fmt_str(const char *line, void *arg){
if(new_line != NULL){
p = strchr(new_line, '|');
if(p != NULL){
strcpy(p, "\0");
strcpy(temp, new_line);
strcat(temp, "\r\n");
strcat(temp, p+1);
if(p != NULL){ /* Wenn ein | gefunden wurde */
strcpy(p, "\0"); /* dann diesen durch ein Stringende ersetzen */
strcpy(temp, new_line); /* Das Srueck vor dem | in einen Puffer schreiben */
strcat(temp, "\r\n"); /* ein zeilenumbruch mit Wagenruecklauf einfuegen */
strcat(temp, p+1); /* das stueck hinter dem | anfuegen */
} else {
strcpy(temp, new_line);
strcpy(temp, new_line); /* Wenn kein | gefunden, dann den ganzen String in den Puffer */
}
if (*dest) free(*dest);
@ -110,24 +114,28 @@ static int read_fmt_str(const char *line, void *arg){
}
/* Liest ein double ein */
static int read_double(const char *line, void *arg){
double *dest = arg;
*dest = atof(line);
return 1;
}
/* Liest eine Farbe ein
* Format: rr:gg:bb:aa */
static int read_color(const char *line, void *arg){
img_color_ptr *col = arg;
img_color_ptr tmp = NULL;
char *buff = malloc(sizeof(char)*3);
if(strlen(line) == 11){
if (strchr(line, ':') != NULL){
tmp = malloc(sizeof(img_color_t));
tmp->r = strtol(strncpy(buff, line, 2), NULL, 16);
tmp->b = strtol(strncpy(buff, line+3, 2), NULL, 16);
tmp->g = strtol(strncpy(buff, line+6, 2), NULL, 16);
tmp->alpha = strtol(strncpy(buff, line+9, 2), NULL, 16);
if(strlen(line) == 11){ /* Wenn String auch wirkle 11 Zeichen lang */
if (strchr(line, ':') != NULL){ /* und min. 1 : vorkommt */
tmp = malloc(sizeof(img_color_t)); /* Neues Farbelement allocieren */
tmp->r = strtol(strncpy(buff, line, 2), NULL, 16); /* r */
tmp->b = strtol(strncpy(buff, line+3, 2), NULL, 16); /* b */
tmp->g = strtol(strncpy(buff, line+6, 2), NULL, 16); /* g */
tmp->alpha = strtol(strncpy(buff, line+9, 2), NULL, 16); /* alpha */
DEBUGOUT5(" Farbe gelesen: rot:%2x gelb:%2x gruen:%2x mit alpha:%2x\n", tmp->r, tmp->b, tmp->g, tmp->alpha) ;
}
@ -150,22 +158,22 @@ static int read_time(const char *line, void *arg){
char *p = NULL;
char *tmp = strdup(line);
p = strchr(tmp, '\0');
p = strchr(tmp, '\0'); /* P auf das ende des Strings setzen */
if(p != NULL){
switch( *(p - 1) ){
case 's':
switch( *(p - 1) ){ /* Letztes Zeichen pruefen */
case 's': /* Sekunden */
mult = 1;
break;
case 'm':
case 'm': /* Minuten */
mult = 60;
break;
case 'h':
case 'h': /* Stunden */
mult = 3600;
break;
case 'd':
case 'd': /* Tage */
mult = 86400;
break;
case 'y':
case 'y': /* Jahre */
mult = 31536000;
break;
default:
@ -189,12 +197,15 @@ int get_image_cfg(char *file){
int ret_var;
char *buff;
/* Config - URL zusammenbauen */
buff = malloc(sizeof(char)*(strlen(file)+strlen(global_opts.image_cfg_location)+1));
buff = strcpy(buff, global_opts.image_cfg_location);
buff = strcat(buff, file);
DEBUGOUT2("\nLese Config-File: '%s' \n", buff);
/* File einlesen */
ret_var = read_config(buff, 1, keywords);
return ret_var;
}

View File

@ -1,6 +1,6 @@
/*
chart.c -- Part of Chart-generator for the weatherstation
image_config.h -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
@ -20,4 +20,7 @@
*/
/* Bild - Config holen.
* Argument: Dateiname des Config - Files
* Rueckgabe: 1 bei Erfolg */
int get_image_cfg(char *);

View File

@ -1,3 +1,25 @@
/*
image_data.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
@ -12,14 +34,15 @@
#define BUFFSIZE 512
static pix_list_ptr min = NULL;
static pix_list_ptr max = NULL;
double real_min = 0;
double real_max = 0;
static long base_time; /* Zeit an der 0-Koordinate (lt. Datenbank!) */
/* Variablen */
static pix_list_ptr min = NULL; /* Pointer auf min - Element */
static pix_list_ptr max = NULL; /* Pointer auf Max - Element */
double real_min = 0; /* Realer Max - Wert */
double real_max = 0; /* Realer Min - Wert */
static long base_time; /* Zeit an der 0-Koordinate (lt. Datenbank!) */
/* Funktionsdefinitionen */
static pix_list_ptr add_pix_value(pix_list_ptr , long, int , int );
static char *get_conn_string();
static PGconn *pg_check_connect(char *);
@ -29,11 +52,11 @@ static char *get_type_table_by_id(PGconn *, int );
/* Bibt die Liste mit den y-Labels zurueck */
label_list_ptr get_y_label_list(int c_hight, int padding){
int max_val = 0;
int min_val = 0;
double factor = 0;
int diff = 0;
double real_diff = 0;
int max_val = 0; /* Maximaler Wert */
int min_val = 0; /* Minimaler Wert */
double factor = 0; /* Pixel / Werte */
int diff = 0; /* Wertebereich */
double real_diff = 0; /* Realer Wertebereich */
double padd_val = 0;
int temp = 0;
double koeff = 1;
@ -52,6 +75,7 @@ label_list_ptr get_y_label_list(int c_hight, int padding){
DEBUGOUT1("\nBaue y-Labels...\n");
DEBUGOUT4(" Max. Wert: %d, Min. Wert: %d (inkl. Koeffizient: %3.3f)\n", max_val, min_val, img_cfg.val_koeff);
/* Max und min festlegen */
if (!img_cfg.label_sum){
max_val = ceil( ( ((double)max->value_sum) / ((double)max->value_count) ) * img_cfg.val_koeff);
min_val = floor( ( ((double)min->value_sum) / ((double)min->value_count) ) * img_cfg.val_koeff);
@ -59,10 +83,12 @@ label_list_ptr get_y_label_list(int c_hight, int padding){
max_val = ceil( ( ((double)max->value_sum) ) * img_cfg.val_koeff);
min_val = floor( ( ((double)min->value_sum) ) * img_cfg.val_koeff);
}
/* Min 0 setzen wenn zero_min gesetzt */
if (img_cfg.zero_min){
min_val = 0;
}
/* Rechnen ... */
diff = max_val - min_val;
factor = ( ((double)c_hight - (2 * padding)) / ((double)diff) );
padd_val = (1 / factor) * ((double)padding);
@ -90,22 +116,30 @@ label_list_ptr get_y_label_list(int c_hight, int padding){
temp++;
}
/* Puffer fuer die Labels */
buff = malloc(sizeof(char)*BUFFSIZE);
/* Labels generieren */
for (i = 0; i < num; i++){
/* Momentaner wert */
new_val = temp + (i * interval);
/* Labels zusammenbauen */
if(img_cfg.unit != NULL){
snprintf(buff, BUFFSIZE, "%d%s", new_val, img_cfg.unit);
} else {
snprintf(buff, BUFFSIZE, "%d", new_val);
}
/* Neues Label - Element */
new_ptr = malloc(sizeof(label_list_t));
new_ptr->pos = floor( (real_max - ((double)new_val) ) * factor);
new_ptr->value = new_val;
new_ptr->text = strdup(buff);
new_ptr->next = NULL;
/* Rueckgabe- und Temp-pointer zuweisen */
if (ptr != NULL){
temp_ptr->next = new_ptr;
temp_ptr = temp_ptr->next;
@ -138,16 +172,23 @@ label_list_ptr get_x_label_list(int c_width){
DEBUGOUT1("\nBaue x-Labels...\n");
/* Labels generieren */
for ( i = 1; i < num; i++ ) {
/* aktueller Timestamp */
timestamp = base_time + (i * img_cfg.label_interval);
/* Text fuer das Label bauen */
strftime(buff, BUFFSIZE, img_cfg.x_fmt, localtime(&timestamp) );
/* Neues Label - Element */
new_ptr = malloc(sizeof(label_list_t));
new_ptr->pos = floor( ((double)i) * factor);
new_ptr->value = base_time + (i * img_cfg.label_interval);
new_ptr->text = strdup(buff);
new_ptr->next = NULL;
/* Rueckgabe- und Temp-pointer zuweisen */
if (ptr != NULL){
temp_ptr->next = new_ptr;
temp_ptr = temp_ptr->next;
@ -168,26 +209,31 @@ label_list_ptr get_x_label_list(int c_width){
/* Skaliert die X-Koordinaten der Punkte im angegebenem Bereich
* ausführliche Beschreibung im header-file */
* ausfuehrliche Beschreibung im header-file */
int scale_y_coords(pix_list_ptr ptr, int c_height){
double range = (((real_max - real_min) / img_cfg.val_koeff ) + 1) ; /* Anzahl von 0,1-Schritten */
double pix_per_scale = ((double)c_height) / ((double)range); /* Pixel pro 0,1 */
pix_list_ptr temp = ptr;
int zero_line = floor( ((double)((real_max / img_cfg.val_koeff) + 1)) * pix_per_scale); /* Nullinie */
double range = (((real_max - real_min) / img_cfg.val_koeff ) + 1) ; /* Anzahl von 0,1-Schritten */
double pix_per_scale = ((double)c_height) / ((double)range); /* Pixel pro 0,1 */
int zero_line = floor( ((double)((real_max / img_cfg.val_koeff) + 1)) * pix_per_scale); /* Nullinie */
pix_list_ptr temp = ptr; /* Temporaerer Pointer zum durchgehen der Liste */
DEBUGOUT1("\nBerechne y-Koordinaten:\n");
/* Liste duchgehen */
for (; temp; temp = temp->next){
/* unterscheidung ob summiert oder gemittelt werden soll */
if(!img_cfg.label_sum){
temp->y_pix_coord = (-1 * floor( ( ((double)temp->value_sum) / ((double)temp->value_count) ) * pix_per_scale)) + zero_line;
} else {
temp->y_pix_coord = (-1 * floor( ((double)temp->value_sum) * pix_per_scale)) + zero_line;
}
DEBUGOUT3(" neue y-Koordinate: %d bei x: %d\n",temp->y_pix_coord, temp->x_pix_coord);
}
DEBUGOUT2(" Nullinie bei: %d\n", zero_line);
DEBUGOUT2(" Nullinie bei: %d\n", zero_line);
/* Wenn Nullinie zu sehen, dann die Position zurueckgeben */
if ((real_max - real_min + 1) >= real_max){
return zero_line;
} else {
@ -195,16 +241,20 @@ int scale_y_coords(pix_list_ptr ptr, int c_height){
}
}
/* Maximaler wert */
pix_list_ptr get_max_val(){
return min;
}
/* Minimaler Wert */
pix_list_ptr get_min_val(){
return max;
}
/* Maximale Zeit */
char *get_max_time(){
char *buff = malloc(sizeof(char)*BUFFSIZE);
time_t timestamp = base_time + img_cfg.show_interval;
@ -214,6 +264,8 @@ char *get_max_time(){
return buff;
}
/* Minimale Zeit */
char *get_min_time(){
char *buff = malloc(sizeof(char)*BUFFSIZE);
time_t timestamp = base_time ;
@ -223,6 +275,7 @@ char *get_min_time(){
return buff;
}
/* Holt eine Liste mit den Werten und den jeweiligen x-koordinaten */
pix_list_ptr get_pix_list(int c_width){
double seconds_per_pix = ((double)c_width)/((double)img_cfg.show_interval); /* Pixel pro Sekunde */
@ -234,7 +287,7 @@ pix_list_ptr get_pix_list(int c_width){
int time_field; /* Id ses Timestamp-Feldes */
int val_field; /* Id des Wert - Feldes */
long time_temp; /* Hilfsvariable */
int pix_coord; /* x - Koordinate, an die der Wert gehört */
int pix_coord; /* x - Koordinate, an die der Wert gehoert */
int i, s, t, u; /* Laufvariable zum durchlaufen des Datenbank-resuls */
long timestamp;
pix_list_ptr list_ptr = NULL; /* Zeiger auf den Anfang der Wertliste */
@ -243,46 +296,78 @@ pix_list_ptr get_pix_list(int c_width){
DEBUGOUT1("\nHole Daten...\n");
DEBUGOUT2(" Ein Pixel entspricht %f sekunden\n", seconds_per_pix);
/* Tabellenname holen */
if (img_cfg.manual_table) {
table = strdup(img_cfg.table_name);
} else {
table = get_type_table_by_id(conn, img_cfg.sens_id);
}
/* Anfrage zusammenbauen */
snprintf(query, BUFFSIZE, "SELECT round(date_part('epoch', current_timestamp)) AS now, round(date_part('epoch', timestamp)) AS times, %s AS val FROM %s WHERE sens_id=%d AND timestamp > (current_timestamp - INTERVAL '%d seconds') ORDER BY times ASC", img_cfg.table_field, table, img_cfg.sens_id, img_cfg.show_interval );
/* Anfrage stellen */
res = pg_check_exec(conn, query);
/* ID's der Felder ermitteln */
time_field = PQfnumber(res, "times");
val_field = PQfnumber(res, "val");
base_time = atol(PQgetvalue(res, 0, PQfnumber(res, "now"))) - img_cfg.show_interval;
/* Momentane Zeit */
if(PQntuples(res) > 0){
base_time = atol(PQgetvalue(res, 0, PQfnumber(res, "now"))) - img_cfg.show_interval;
} else {
base_time = time(NULL);
}
/* Ergebnisse durchlaufen */
for (i = 0; i < PQntuples(res); i++){
timestamp = atol(PQgetvalue(res, i, time_field));
time_temp = timestamp - base_time;
/* Wenn Balken gezeichnet werden sollen */
if(img_cfg.bars){
time_temp --;
if(time_temp < 1)
time_temp++;
time_temp = floor( ((double)time_temp) / ((double)img_cfg.label_interval) ) * img_cfg.label_interval;
}
/* Koordinate berechnen */
pix_coord = floor( ((double)time_temp) * seconds_per_pix) ;
/* Listenelement generieren */
temp_ptr = add_pix_value(temp_ptr, timestamp, pix_coord, atoi( PQgetvalue(res, i, val_field) ) );
/* Rueckgabe- und Max/Min-pointer zuweisen */
if (list_ptr == NULL){
list_ptr = temp_ptr;
/* Globale Variablen neu initialisieren um
* mehtete Bilder in einem Thread bauen zu
* können */
* koennen */
min = temp_ptr;
max = temp_ptr;
}
}
/* Wenn keine Daten vorhanden, dann Fake - Element generieren */
if(i == 0){
timestamp = timestamp - base_time +1;
if(img_cfg.bars){
time_temp = floor( ((double)timestamp) / ((double)img_cfg.label_interval) ) * img_cfg.label_interval;
} else {
time_temp = timestamp;
}
pix_coord = floor( ((double)time_temp) * seconds_per_pix) ;
temp_ptr = add_pix_value(temp_ptr, timestamp, pix_coord, 0 );
list_ptr = temp_ptr;
min = temp_ptr;
max = temp_ptr;
}
/* Min / Max ermitteln */
temp_ptr = list_ptr;
u = 1;
@ -313,6 +398,8 @@ pix_list_ptr get_pix_list(int c_width){
DEBUGOUT2(" %d Werte geholt \n", i);
DEBUGOUT3(" Min: x-pos.: %d, Wert: %d\n", min->x_pix_coord, (min->value_sum / min->value_count) );
DEBUGOUT3(" Max: x-pos.: %d, Wert: %d\n", max->x_pix_coord, (max->value_sum / max->value_count) );
/* Aufraemen */
PQclear(res);
PQfinish(conn);
free(query);
@ -325,6 +412,7 @@ pix_list_ptr get_pix_list(int c_width){
/* Speichert einen geholten Wert ab */
static pix_list_ptr add_pix_value(pix_list_ptr ptr, long timestamp, int coord, int value){
/* Erstes Element */
if(ptr == NULL){
DEBUGOUT1("\nLese Daten ein:\n");
ptr = malloc(sizeof(pix_list_t));
@ -336,11 +424,13 @@ static pix_list_ptr add_pix_value(pix_list_ptr ptr, long timestamp, int coord, i
DEBUGOUT3(" Erstes Element generiert...x-pos.: %d Wert: %d\n",ptr->x_pix_coord, ptr->value_sum);
} else {
/* Wenn schon ein Wert fuer X - Koordinate vorhanden,
* dann aufsummieren, sonst neues Element anfuegen */
if(coord == ptr->x_pix_coord){
ptr->value_sum += value;
ptr->value_count++;
DEBUGOUT5(" Zu x-pos. %d %d. Wert (%d) hinzugefügt. Durchschn.: %d\n", ptr->x_pix_coord, ptr->value_count, value, (ptr->value_sum/ptr->value_count) );
DEBUGOUT5(" Zu x-pos. %d %d. Wert (%d) hinzugefuegt. Durchschn.: %d\n", ptr->x_pix_coord, ptr->value_count, value, (ptr->value_sum/ptr->value_count) );
} else {
ptr->next = malloc(sizeof(pix_list_t));
ptr = ptr->next;
@ -385,7 +475,7 @@ static PGresult *pg_check_exec(PGconn *conn, char *query){
DEBUGOUT2("Fehler beim exec: %s\n", query);
exit_error(ERROR_QUERY);
} else {
DEBUGOUT2("Query: '%s' ausgeführt\n", query);
DEBUGOUT2("Query: '%s' ausgefuehrt\n", query);
}
return res;
}

View File

@ -1,21 +1,44 @@
/*
image_data.h -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Liste mit den Werten fuer das Diagram */
typedef struct pix_list *pix_list_ptr;
typedef struct pix_list {
pix_list_ptr next;
int x_pix_coord;
int y_pix_coord;
int value_count;
int value_sum;
pix_list_ptr next; /* naechstes Element */
int x_pix_coord; /* X - Koordinate */
int y_pix_coord; /* Y - Koordinate */
int value_count; /* Anzahl der Werte */
int value_sum; /* Summe der Werte */
} pix_list_t;
/* Liste mit Labels */
typedef struct label_list *label_list_ptr;
typedef struct label_list {
int pos;
long value;
char *text;
label_list_ptr next;
int pos; /* Position (X oder Y) */
long value; /* Wert */
char *text; /* Anzuzeigender Text */
label_list_ptr next; /* naechstes Element */
} label_list_t;
@ -35,7 +58,11 @@ pix_list_ptr get_min_val();
pix_list_ptr get_max_val();
/* Max. Zeit */
char *get_max_time();
/* Min. Zeit */
char *get_min_time();
@ -53,4 +80,10 @@ int scale_y_coords(pix_list_ptr , int );
*/
label_list_ptr get_x_label_list(int );
/* Baut die Liste mit den Labels an der Y-Achse
* 1. Argument: Hoehe des Bildes
* 2. Argument: Einrueckung oben und unten
* Rueckgabe: List mit den Labels
* */
label_list_ptr get_y_label_list(int, int);

View File

@ -1,3 +1,25 @@
/*
image_draw.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -10,22 +32,27 @@
#define SHORTBUFFSIZE 64
/* der besseren Lesbarkeit wegen einen Farbtyp definiert */
typedef int color;
/* Datenstruktur, welche die Dimensionen eines Textes enthaelt */
typedef struct dimension {
int width;
int height;
int l_t_x;
int l_t_y;
int l_b_x;
int l_b_y;
int r_b_x;
int r_b_y;
int r_t_x;
int r_t_y;
int to_base;
int width; /* Breite */
int height; /* Hoehe */
int l_t_x; /* Links - oben - x */
int l_t_y; /* Links - oben - y */
int l_b_x; /* Links - unten - x */
int l_b_y; /* Links - unten - y */
int r_b_x; /* Rechts - unten - x */
int r_b_y; /* Rechts - unten - y */
int r_t_x; /* Rechts - oben - x */
int r_t_y; /* Rechts - oben - y */
int to_base; /* Abstand von oben zur Grundlinie */
} dimension_t;
/* Funktionsdefinitionen */
static gdImagePtr create_image();
static gdImagePtr draw_image(gdImagePtr);
static dimension_t calc_text_dim(char *, double , double );
@ -33,11 +60,11 @@ static color alloc_alpha_color(gdImagePtr , img_color_ptr );
static void write_image_png(gdImagePtr, FILE *);
/* Baut ein Bild und schreibt es in die Datei */
int draw_to_file(FILE *fd){
gdImagePtr img = create_image();
draw_image(img);
write_image_png(img, fd);
gdImageDestroy(img);
void draw_to_file(FILE *fd){
gdImagePtr img = create_image(); /* Bild 'erschaffen' */
draw_image(img); /* Bild zeichnen */
write_image_png(img, fd); /* Bild schreiben */
gdImageDestroy(img); /* Bild 'zerstoeren */
}
/* Erstellt ein Bild mit Hintergrundfarbe */
@ -81,7 +108,7 @@ static gdImagePtr draw_image(gdImagePtr img){
char *buff;
time_t ts;
/* Größenangaben fuer die einzelnen Texte */
/* Groeßenangaben fuer die einzelnen Texte */
dimension_t head_d;
dimension_t y_label_d;
dimension_t x_label_d;
@ -123,7 +150,7 @@ static gdImagePtr draw_image(gdImagePtr img){
/* Diagramhöhe */
/* Diagramhoehe */
buff = malloc(sizeof(char)*SHORTBUFFSIZE);
ts = time(NULL);
strftime(buff, SHORTBUFFSIZE, "%d.%m.%y\r\n%H:%M", localtime(&ts) ) ;
@ -196,11 +223,10 @@ static gdImagePtr draw_image(gdImagePtr img){
/* Rahmen */
gdImageRectangle(img, offset_x_left, offset_y_top, img_cfg.width - offset_x_right, img_cfg.height - offset_y_bottom, dia_border_c);
}
/* Berechnet die Dimensionen eines Textes */
static dimension_t calc_text_dim(char *text, double size, double angle){
int brect[8];
dimension_t dim;
@ -209,8 +235,10 @@ static dimension_t calc_text_dim(char *text, double size, double angle){
int y_rt_lb = 0;
int y_rb_lt = 0;
/* Dimmensionen holen */
gdImageStringFT(NULL, &brect[0], 0, IMG_FONT, size, angle, 0,0, text);
/* Zuweisen */
dim.l_t_x = brect[6];
dim.l_t_y = brect[7];
dim.l_b_x = brect[0];
@ -220,8 +248,10 @@ static dimension_t calc_text_dim(char *text, double size, double angle){
dim.r_t_x = brect[4];
dim.r_t_y = brect[5];
/* Abstand zur Grundlinie */
dim.to_base = 0 - dim.r_t_y;
/* Abstaende berechnen */
x_rt_lb = dim.r_t_x - dim.l_b_x;
x_rb_lt = dim.r_b_x - dim.l_t_x;
y_rt_lb = dim.l_b_y - dim.r_t_y;
@ -235,13 +265,10 @@ static dimension_t calc_text_dim(char *text, double size, double angle){
if(y_rt_lb < y_rb_lt){
dim.height = y_rb_lt;
//printf("y_rb_lt");
} else {
dim.height = y_rt_lb;
//printf("y_rt_lb");
}
//printf("%d -- %s\n", dim.height, text);
return dim;
}

View File

@ -1,2 +1,25 @@
/*
int draw_to_file(FILE *);
image_config.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Bild generieren und in eine Datei schreiben
* Argument: Datei */
void draw_to_file(FILE *);

View File

@ -1,6 +1,6 @@
/*
process_image.c -- Part of Chart-generator for the weatherstation
image_file.c -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
@ -39,6 +39,7 @@
image_cfg_t img_cfg;
/* Funktionsdefinitionen */
static void regenerate_image();
static int check_file_interval();
@ -52,6 +53,8 @@ void process_image_cfg(char *image_cfg_file){
get_image_cfg(image_cfg_file);
if (img_cfg.file_name != NULL){
/* Debugausgabe einiger Config - Optionen */
DEBUGOUT2("File-Name = %s\n", img_cfg.file_name);
DEBUGOUT2("Ueberschr. = %s\n", img_cfg.headline);
DEBUGOUT2("Gen.Interval = %d\n", img_cfg.gen_interval);
@ -66,6 +69,7 @@ void process_image_cfg(char *image_cfg_file){
DEBUGOUT2("TabellenName = %s\n", img_cfg.table_name);
DEBUGOUT1("\n");
/* Bild - Namen zusammenbauen */
if(img_cfg.dflt_dir){
buff = malloc(sizeof(char)*BUFFSIZE);
buff = strncpy(buff, global_opts.dflt_image_location, BUFFSIZE - 1);
@ -77,11 +81,12 @@ void process_image_cfg(char *image_cfg_file){
} else {
return;
}
/* Pruefen ob Generierung noetig */
if(check_file_interval()){
regenerate_image();
regenerate_image(); /* generieren */
}
//sleep(30);
}
@ -93,11 +98,14 @@ static int check_file_interval(){
time_t now;
long diff_sek;
/* Pruefen ob Bild vorhanden */
if(access(img_cfg.file_name, F_OK) == -1){
DEBUGOUT2("Datei '%s' existiert nicht\n", img_cfg.file_name);
DEBUGOUT1("Sie muss neu generiert werden!\n");
return 1;
}
/* Pruefen ob Bild zu alt */
if ((stat(img_cfg.file_name, &stat_buff)) != -1){
now = time(NULL);
@ -118,7 +126,9 @@ static int check_file_interval(){
return 0;
}
/* Bild (neu-) generieren */
static void regenerate_image(){
FILE *fd = fopen(img_cfg.file_name, "wb");
draw_to_file(fd);
FILE *fd = fopen(img_cfg.file_name, "wb"); /* Datei oeffnen */
draw_to_file(fd); /* Bild bauen und in Datei schreiben */
fclose(fd); /* Datei schließen */
}

View File

@ -1,6 +1,6 @@
/*
process_image.h -- Part of Chart-generator for the weatherstation
image_file.h -- Part of Chart-generator for the weatherstation
Copyright (C) 2006 Jan Losinski
@ -20,4 +20,7 @@
*/
/* Image bei Bedarf
* generieren und in Datei schreiben.
* Argument: Filename des Config - Files*/
void process_image_cfg(char *);