Allgemein über Datenlogger, Kommunikation, DFÜ
Moderator: Mod-Team
von zagibu » 12.08.2010, 09:05
Der Solarmax Wechselrichter scheint am Morgen, wenn er einschaltet, bereits Verbindungen anzunehmen, aber eine Weile noch keine Daten zu liefern. Das ist für den momentanen Logger noch problematisch, und ich muss die TCP-Geschichte umschreiben, um diesen Fakt zu adressieren.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von zagibu » 12.08.2010, 13:32
So, dies ist der Code, welcher non-blocking reads durchführt. Morgen werden wir sehen, ob's wirklich daran lag: - Code: Alles auswählen
/* Simple solarmax logger c program written by zagibu@gmx.ch in July 2010 This program is licensed under WTFPL 2 http://sam.zoy.org/wtfpl/
# ./logger hostname port loginterval
Sources: - http://www.linuxhowtos.org/C_C++/socket.htm - http://wwwuser.gwdg.de/~kboehm/ebook/21_kap15_w6.html#49329 - http://man.cx/setbuf%283%29 - http://allfaq.org/forums/t/169895.aspx - http://dev.mysql.com/tech-resources/articles/mysql-capi-tutorial.html */
#define _GNU_SOURCE
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <mysql/mysql.h> #include <regex.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <errno.h>
#define DEBUG 1
FILE* error_file = NULL; char* error_file_name = "/var/log/solarmax-error.log"; char* error_mode = "w"; FILE* debug_file = NULL; char* debug_file_name = "/var/log/solarmax-debug.log"; char* debug_mode = "w";
void error_exit(const char* msg) { perror(msg); if (error_file != NULL) fclose(error_file); if (debug_file != NULL) fclose(debug_file); exit(0); }
void debug_entry(char* msg) { time_t timestamp = time(NULL); char debug_msg[512]; char *time_now = ctime(×tamp); time_now[strlen(time_now)-1]=0; if (debug_file == NULL) error_exit("ERROR writing to debug.log file"); sprintf(debug_msg, "%s %s", time_now, msg); fprintf(debug_file, "%s\n", debug_msg); }
void error_retry(char* msg) { time_t timestamp = time(NULL); char error_msg[512]; char *time_now = ctime(×tamp); time_now[strlen(time_now)-1]=0; if (error_file == NULL) error_exit("ERROR writing to error.log file"); sprintf(error_msg, "%s %s", time_now, msg); fprintf(error_file, "%s\n", error_msg); }
void set_nonblock(int sock) { int flags; flags = fcntl(sock,F_GETFL,0); if (flags == -1) error_exit("ERROR no valid flags on socket"); fcntl(sock, F_SETFL, flags | O_NONBLOCK); }
int main(int argc, char *argv[]) { int sockfd, portno, n, log_interval, result, counter; struct sockaddr_in serv_addr; struct hostent* server; char* dbhost = "localhost"; char* dbname = "solarmax"; char* dbuser = "user"; char* dbpass = "password"; char* message = "{FB;01;46|64:KDY;KMT;KYR;KT0;TNF;TKK;PAC;PRL;IL1;IDC;UL1;UDC;SYS|1199}"; char* expression = "...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*)"; int kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys; char buffer[512], buffer2[512]; char query[512]; char* temp; regex_t rx; regmatch_t* matches; MYSQL* connection = NULL;
// Check commandline arguments if (argc < 4) error_exit("ERROR program needs hostname, port and loginterval (in seconds) as parameters");
// Try to open error log file if ((error_file = fopen(error_file_name, error_mode)) == NULL) error_exit("ERROR opening error.log file");
// Make file unbuffered setbuf(error_file, NULL);
// Try to open debug log file, if necessary if(DEBUG) { if((debug_file = fopen(debug_file_name, debug_mode)) == NULL) error_exit("ERROR opening debug.log file");
// Make file unbuffered setbuf(debug_file, NULL); }
// Get log interval from command line argument log_interval = atoi(argv[3]);
// Try to compile regular expression result = regcomp(&rx, expression, REG_EXTENDED); if (result != 0) { regerror(result, &rx, expression, sizeof(expression)); regfree(&rx); sprintf(buffer, "ERROR invalid regular expression: %s", expression); error_exit(buffer); }
// Try to reserve memory for matches matches = (regmatch_t *) malloc((rx.re_nsub + 1) * sizeof(regmatch_t)); if (!matches) error_exit("Out of memory");
// Connect to database connection = mysql_init(NULL); if (!mysql_real_connect(connection, dbhost, dbuser, dbpass, dbname, 0, NULL, 0)) error_exit(mysql_error(connection));
if (DEBUG) { sprintf(buffer, "Connected to database %s on host %s", dbname, dbhost); debug_entry(buffer); }
while (1) { // Check if connection to db-server must be re-established if (mysql_ping(connection)) { // Connect to database if (!mysql_real_connect(connection, dbhost, dbuser, dbpass, dbname, 0, NULL, 0)) error_exit(mysql_error(connection));
if (DEBUG) { sprintf(buffer, "Connected to database %s on host %s", dbname, dbhost); debug_entry(buffer); } }
// Try to open socket for communication with solarmax sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { error_retry("Can't open any socket"); sleep(60); continue; }
// Try to resolve solarmax address/hostname server = gethostbyname(argv[1]); if (server == NULL) { sprintf(buffer, "Can't resolve \"%s\"", argv[1]); error_retry(buffer); sleep(60); continue; }
// Try to establish a connection with solarmax portno = atoi(argv[2]); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { sprintf(buffer, "%s: Can't connect to solarmax (%s) on port %d", strerror(errno), argv[1], portno); error_retry(buffer); sleep(60); continue; }
// Make socket non-blocking set_nonblock(sockfd);
if (DEBUG) { sprintf(buffer, "Connected to solarmax (%s) on port %d", argv[1], portno); debug_entry(buffer); }
// Start sending the data requests and logging the answers while (1) { if (DEBUG) { sprintf(buffer, "Sending message: %s", message); debug_entry(buffer); }
// Send message n = write(sockfd,message,strlen(message)); if (n < 0) { error_retry("ERROR sending TCP packet"); close(sockfd); break; }
// Read answer bzero(buffer, 256); n = read(sockfd, buffer, 255); for (counter = 0; counter < 10 && n < 0 && errno == EAGAIN; counter++) { if (DEBUG) debug_entry("Socket contains no data, trying to read again later"); sleep(1); n = read(sockfd, buffer, 255); }
if (n < 0) { error_retry("ERROR receiving TCP packet"); close(sockfd); break; }
if (DEBUG) { sprintf(buffer2, "Received answer: %s", buffer); debug_entry(buffer2); }
// Extract the data fields from answer result = regexec(&rx, buffer, rx.re_nsub + 1, matches, 0); if (result) { regerror(result, &rx, buffer, sizeof(buffer)); error_exit("ERROR no regexp match"); }
// Convert the extracted data fields to integer values temp = strndup(buffer + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); kdy = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); kmt = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so); kyr = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so); kt0 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[5].rm_so, matches[5].rm_eo - matches[5].rm_so); tnf = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so); tkk = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so); pac = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[8].rm_so, matches[8].rm_eo - matches[8].rm_so); prl = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[9].rm_so, matches[9].rm_eo - matches[9].rm_so); il1 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[10].rm_so, matches[10].rm_eo - matches[10].rm_so); idc = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[11].rm_so, matches[11].rm_eo - matches[11].rm_so); ul1 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[12].rm_so, matches[12].rm_eo - matches[12].rm_so); udc = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[13].rm_so, matches[13].rm_eo - matches[13].rm_so); sys = strtol(temp, NULL, 16); free(temp);
// Construct the query sprintf(query, "INSERT INTO log (kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys) VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d);", kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys);
if (DEBUG) { sprintf(buffer, "Executing query: %s", query); debug_entry(buffer); }
// Execute the query to write the data into db mysql_query(connection, query); if (mysql_errno(connection)) error_exit(mysql_error(connection));
// Wait for the specified number of seconds sleep(log_interval); } }
return 0; }
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von zagibu » 13.08.2010, 09:01
Das Problem ist behoben. Hier nun der vorerst finale Code. Ich habe noch die Debug- und wiederkehrenden Error-Messages ausgeschalten, damit die Log-Files sich nicht zur Unendlichkeit aufblähen. Wer den Logger sowieso am Abend killt und am Morgen neu startet, kann DEBUG wieder auf 1 setzen und die auskommentierten Zeilen wieder aktivieren, denn die Logs werden bei jedem Neustart des Loggers gespült: - Code: Alles auswählen
/* Simple solarmax logger c program written by zagibu@gmx.ch in July 2010 This program is licensed under WTFPL 2 http://sam.zoy.org/wtfpl/
# ./logger hostname port loginterval
Sources: - http://www.linuxhowtos.org/C_C++/socket.htm - http://wwwuser.gwdg.de/~kboehm/ebook/21_kap15_w6.html#49329 - http://man.cx/setbuf%283%29 - http://allfaq.org/forums/t/169895.aspx - http://dev.mysql.com/tech-resources/articles/mysql-capi-tutorial.html */
#define _GNU_SOURCE
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <mysql/mysql.h> #include <regex.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <errno.h>
#define DEBUG 0
FILE* error_file = NULL; char* error_file_name = "/var/log/solarmax-error.log"; char* error_mode = "w"; FILE* debug_file = NULL; char* debug_file_name = "/var/log/solarmax-debug.log"; char* debug_mode = "w";
void error_exit(const char* msg) { perror(msg); if (error_file != NULL) fclose(error_file); if (debug_file != NULL) fclose(debug_file); exit(0); }
void debug_entry(char* msg) { time_t timestamp = time(NULL); char debug_msg[512]; char *time_now = ctime(×tamp); time_now[strlen(time_now)-1]=0; if (debug_file == NULL) error_exit("ERROR writing to debug.log file"); sprintf(debug_msg, "%s %s", time_now, msg); fprintf(debug_file, "%s\n", debug_msg); }
void error_retry(char* msg) { time_t timestamp = time(NULL); char error_msg[512]; char *time_now = ctime(×tamp); time_now[strlen(time_now)-1]=0; if (error_file == NULL) error_exit("ERROR writing to error.log file"); sprintf(error_msg, "%s %s", time_now, msg); fprintf(error_file, "%s\n", error_msg); }
void set_nonblock(int sock) { int flags; flags = fcntl(sock,F_GETFL,0); if (flags == -1) error_exit("ERROR no valid flags on socket"); fcntl(sock, F_SETFL, flags | O_NONBLOCK); }
int main(int argc, char *argv[]) { int sockfd, portno, n, log_interval, result, counter; struct sockaddr_in serv_addr; struct hostent* server; char* dbhost = "localhost"; char* dbname = "solarmax"; char* dbuser = "logger"; char* dbpass = "m4xx3n"; char* message = "{FB;01;46|64:KDY;KMT;KYR;KT0;TNF;TKK;PAC;PRL;IL1;IDC;UL1;UDC;SYS|1199}"; char* expression = "...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*);...=([0-9A-F]*)"; int kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys; char buffer[512], buffer2[512]; char query[512]; char* temp; regex_t rx; regmatch_t* matches; MYSQL* connection = NULL;
// Check commandline arguments if (argc < 4) error_exit("ERROR program needs hostname, port and loginterval (in seconds) as parameters");
// Try to open error log file if ((error_file = fopen(error_file_name, error_mode)) == NULL) error_exit("ERROR opening error.log file");
// Make file unbuffered setbuf(error_file, NULL);
// Try to open debug log file, if necessary if(DEBUG) { if((debug_file = fopen(debug_file_name, debug_mode)) == NULL) error_exit("ERROR opening debug.log file");
// Make file unbuffered setbuf(debug_file, NULL); }
// Get log interval from command line argument log_interval = atoi(argv[3]);
// Try to compile regular expression result = regcomp(&rx, expression, REG_EXTENDED); if (result != 0) { regerror(result, &rx, expression, sizeof(expression)); regfree(&rx); sprintf(buffer, "ERROR invalid regular expression: %s", expression); error_exit(buffer); }
// Try to reserve memory for matches matches = (regmatch_t *) malloc((rx.re_nsub + 1) * sizeof(regmatch_t)); if (!matches) error_exit("Out of memory");
// Connect to database connection = mysql_init(NULL); if (!mysql_real_connect(connection, dbhost, dbuser, dbpass, dbname, 0, NULL, 0)) error_exit(mysql_error(connection));
if (DEBUG) { sprintf(buffer, "Connected to database %s on host %s", dbname, dbhost); debug_entry(buffer); }
while (1) { // Check if connection to db-server must be re-established if (mysql_ping(connection)) { // Connect to database if (!mysql_real_connect(connection, dbhost, dbuser, dbpass, dbname, 0, NULL, 0)) error_exit(mysql_error(connection));
if (DEBUG) { sprintf(buffer, "Connected to database %s on host %s", dbname, dbhost); debug_entry(buffer); } }
// Try to open socket for communication with solarmax sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { //error_retry("Can't open any socket"); sleep(60); continue; }
// Try to resolve solarmax address/hostname server = gethostbyname(argv[1]); if (server == NULL) { //sprintf(buffer, "Can't resolve \"%s\"", argv[1]); //error_retry(buffer); sleep(60); continue; }
// Try to establish a connection with solarmax portno = atoi(argv[2]); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { //sprintf(buffer, "%s: Can't connect to solarmax (%s) on port %d", strerror(errno), argv[1], portno); //error_retry(buffer); sleep(60); continue; }
// Make socket non-blocking set_nonblock(sockfd);
if (DEBUG) { sprintf(buffer, "Connected to solarmax (%s) on port %d", argv[1], portno); debug_entry(buffer); }
// Start sending the data requests and logging the answers while (1) { if (DEBUG) { sprintf(buffer, "Sending message: %s", message); debug_entry(buffer); }
// Send message n = write(sockfd,message,strlen(message)); if (n < 0) { //error_retry("ERROR sending TCP packet"); close(sockfd); break; }
// Read answer bzero(buffer, 256); n = read(sockfd, buffer, 255); for (counter = 0; counter < 10 && n < 0 && errno == EAGAIN; counter++) { if (DEBUG) debug_entry("Socket contains no data, trying to read again later"); sleep(1); n = read(sockfd, buffer, 255); }
if (n < 0) { //error_retry("ERROR receiving TCP packet"); close(sockfd); break; }
if (DEBUG) { sprintf(buffer2, "Received answer: %s", buffer); debug_entry(buffer2); }
// Extract the data fields from answer result = regexec(&rx, buffer, rx.re_nsub + 1, matches, 0); if (result) { regerror(result, &rx, buffer, sizeof(buffer)); error_exit("ERROR no regexp match"); }
// Convert the extracted data fields to integer values temp = strndup(buffer + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); kdy = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); kmt = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so); kyr = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so); kt0 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[5].rm_so, matches[5].rm_eo - matches[5].rm_so); tnf = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so); tkk = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so); pac = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[8].rm_so, matches[8].rm_eo - matches[8].rm_so); prl = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[9].rm_so, matches[9].rm_eo - matches[9].rm_so); il1 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[10].rm_so, matches[10].rm_eo - matches[10].rm_so); idc = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[11].rm_so, matches[11].rm_eo - matches[11].rm_so); ul1 = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[12].rm_so, matches[12].rm_eo - matches[12].rm_so); udc = strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[13].rm_so, matches[13].rm_eo - matches[13].rm_so); sys = strtol(temp, NULL, 16); free(temp);
// Construct the query sprintf(query, "INSERT INTO log (kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys) VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d);", kdy, kmt, kyr, kt0, tnf, tkk, pac, prl, il1, idc, ul1, udc, sys);
if (DEBUG) { sprintf(buffer, "Executing query: %s", query); debug_entry(buffer); }
// Execute the query to write the data into db mysql_query(connection, query); if (mysql_errno(connection)) error_exit(mysql_error(connection));
// Wait for the specified number of seconds sleep(log_interval); } }
return 0; }
Ich werde nun also bis auf weiteres nicht daran weiterarbeiten, es sei denn, jemand stellt Fehler fest.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von zagibu » 14.08.2010, 12:44
Hier ist noch ein Link zum Visualizer, der meine Anlage anzeigt, falls jemand das Ganze in Aktion sehen will: http://node23.net/solarmaxSind halt erst ein paar Tage geloggt, und teilweise noch mit Lücken, aber ich denke man sieht schon, wie es funktionieren sollte.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von zagibu » 19.08.2010, 17:52
Nicht schlecht, Herr Specht. Ich schlage vor, dass du die Linien erst nach dem Gitter zeichnest, sonst löscht es diese stellenweise aus.
Weiterhin könntest du für die Linien den y-Wert des vorherigen Punktes "mitschleppen" und dann statt nem Punkt ne Linie von diesem vorherigen Wert zum neuen machen. Sollte dem Auge helfen, der Linie besser folgen zu können, besonders, wenn die Werte stark herumspringen in einem Abschnitt. Must halt diesen nachgeschleppten Wert vor der Schleife mit 0 initialisieren, und evtl. keine Linie zeichnen, solange der 0 ist.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von lasser » 19.08.2010, 22:18
Moin! zagibu hat geschrieben:Nicht schlecht, Herr Specht.
Danke. Ich schlage vor, dass du die Linien erst nach dem Gitter zeichnest, sonst löscht es diese stellenweise aus.
Ja, bin ich bloß noch nicht zu gekommen. Das wird etwas besser aussehen. Weiterhin könntest du für die Linien den y-Wert des vorherigen Punktes "mitschleppen" und dann statt nem Punkt ne Linie von diesem vorherigen Wert zum neuen machen. Sollte dem Auge helfen, der Linie besser folgen zu können, besonders, wenn die Werte stark herumspringen in einem Abschnitt. Must halt diesen nachgeschleppten Wert vor der Schleife mit 0 initialisieren, und evtl. keine Linie zeichnen, solange der 0 ist.
Ja, auch das wäre viel besser als es jetzt ist. Krieg ich wohl hin. Dabei kommen aber vermutlich "eckige" Kurven bei raus. Noch schöner wäre weiche Kurven, aber da fehlt mir komplett der Überblick...
-
lasser
- Stammmitglied

-
- Beiträge: 109
- Registriert: 16.04.2010, 10:42
- PV-Anlage [kWp]: 5,5
- Info: Betreiber
von zagibu » 20.08.2010, 10:14
Sieht schon viel besser aus. Die Leistung hätte ich aber hinter dem Gitter gelassen, weil dieses sonst unter Umständen grossflächig verdeckt wird, und dann die Höhe der Kurven evtl. nicht mehr gut abgeschätzt werden kann.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von lasser » 20.08.2010, 14:21
Moin! zagibu hat geschrieben:Sieht schon viel besser aus. Die Leistung hätte ich aber hinter dem Gitter gelassen, weil dieses sonst unter Umständen grossflächig verdeckt wird, und dann die Höhe der Kurven evtl. nicht mehr gut abgeschätzt werden kann.
Das habe ich nicht gemacht, weil dann 2 while-Schleifen nötig sind, um die Daten ins Bild zu setzen. Aber ich hab's jetzt trotzdem mal versucht, wird den Rechner schon nicht einknicken lassen... Allerdings wird mit folgendem Code zwar schön das Gitter vor die Leistung gemalt, allerdings tauchen kdy, tkk und udc nicht mehr auf. Und ich find den Fehler nicht. Hier mal der Code zu meiner function draw_day($start, $end), vielleicht siehst Du, woran es liegt (und nicht wundern, ist nicht mehr so schön strukturiert wie bei Dir und alles auf eine Bildbreite von 820 Pixeln ausgerichtet): - Code: Alles auswählen
function draw_day($start, $end) { // Select data from given day //$result = @mysql_query("SELECT HOUR(created) AS hour, MINUTE(created) AS minute, pac FROM log WHERE created BETWEEN '$start' AND '$end'") or die(mysql_error()); $result = @mysql_query("SELECT HOUR(created) AS hour, MINUTE(created) AS minute, pac, kdy, tkk, udc FROM log WHERE created BETWEEN '$start' AND '$end'") or die(mysql_error()); if (mysql_num_rows($result) == 0) { // No data...create dummy image $image = imagecreatetruecolor(10, 10); $white = imagecolorallocate($image, 255, 255, 255); imagefill($image, 0, 0, $white); imagepng($image, 'img/data.png'); imagedestroy($image); return 'Keine Daten für diese Periode.<br />'; }
// Initialize pac image // Sun rise and fall during longest day at your place, must be integer $rise = 6; $fall = 22; // Pixel per hour should be equal to log entries per hour (I log every minute) $px_per_hour = 42; // Width = hours * px per hour + gap //$width = ($fall - $rise) * $px_per_hour + 50; $width = ($fall - $rise) * $px_per_hour +148; $maxpac = 5200; $maxkdy = 40; $maxtkk = 60; $lasttkk = 0; $maxudc = 400; $lastudc = 0; // How many W per diagram line $step_w = 500; $step_kdy = 5; $step_tkk = 8; $step_udc = 40; // How many px per diagram line (W/px = $step_w / $vert_px) $vert_px = 30; // Height = number of lines * px per line + px per line (for 0-line) + gap $height = $maxpac / $step_w * $vert_px + 40; // Create image, prepare colors and set background to white $image = imagecreatetruecolor($width, $height); $white = imagecolorallocate($image, 255, 255, 255); $gray = imagecolorallocate($image, 128, 128, 128); $black = imagecolorallocate($image, 0, 0, 0); $green = imagecolorallocate($image, 0, 196, 64); $blue = imagecolorallocate($image, 0, 0, 255); $red = imagecolorallocate($image, 255, 0, 0); imagefill($image, 0, 0, $white);
// Draw pac values while($row = mysql_fetch_assoc($result)) { // Determine x position $xpos = ($row['hour'] - $rise) * $px_per_hour + $row['minute'] / 60 * $px_per_hour + 25; // Calculate y position with logged pac $pac = $row['pac'] / $step_w * $vert_px; // Draw pac line imageline($image, $xpos, $height - 30, $xpos, $height - 30 - $pac, $green); }
// Draw horizontal lines with some space above and below for ($i = 0; $i <= $maxpac / $step_w; $i++) { // Create horizontal grid line $ypos = $height - $i * $vert_px - 30; imageline($image, 12, $ypos, $width - 110, $ypos, $gray); // Draw the pac value at the end of the horizontal line $pac = $i * $step_w; $kdy = $i * $step_kdy; $tkk = $i * $step_tkk; $udc = $i * $step_udc; imagefttext($image, 7, 0, $width - 109, $ypos + 4, $black, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', $pac); imagefttext($image, 7, 0, $width - 74, $ypos + 4, $blue, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', $kdy); imagefttext($image, 7, 0, $width - 47, $ypos + 4, $black, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', $tkk); imagefttext($image, 7, 0, $width - 25, $ypos + 4, $red, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', $udc); }
// Draw vertical lines with some space at the left and right for ($i = 0; $i <= $fall - $rise; $i++) { // Create vertical grid line $xpos = $i * $px_per_hour + 25; imageline($image, $xpos, 5, $xpos, $height - 25, $gray); // Draw the hour value at the end of the vertical line $hour = ($i + $rise) % 24 . ':00'; imagefttext($image, 8, 0, $xpos - 10, $height - 12, $black, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', $hour); }
imagefttext($image, 7, 0, $width - 107, 10, $black, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', "(W)"); imagefttext($image, 6, 0, $width - 84, 10, $blue, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', "(kW/h)"); imagefttext($image, 6, 0, $width - 50, 10, $black, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', "(°C)"); imagefttext($image, 7, 0, $width - 25, 10, $red, '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', "(V)"); // Draw other logged values: kdy, tkk, udc while($row = mysql_fetch_assoc($result)) { // Determine x position $xpos = ($row['hour'] - $rise) * $px_per_hour + $row['minute'] / 60 * $px_per_hour + 25; $lastxpos = $xpos; // Logged kdy is ten times as high as effective $kdy = $row['kdy'] / 10 / $step_kdy * $vert_px; // Draw kdy dot imagesetpixel($image, $xpos, $height - 30 - $kdy, $blue); // draw tkk as a stair-line $tkk = $row['tkk'] / $step_tkk * $vert_px; if ($lasttkk == 0) { imagesetpixel($image, $xpos, $height - 30 - $tkk, $black); } else { imageline($image, $lastxpos, $height - 30 - $lasttkk, $xpos, $height - 30 - $tkk, $black); } $lasttkk = $tkk; // Logged udc is ten times as high as effective $udc = $row['udc'] / 10 / $step_udc * $vert_px; if ($lastudc == 0) { imagesetpixel($image, $xpos, $height - 30 - $udc, $red); } else { imageline($image, $lastxpos, $height - 30 - $lastudc, $xpos, $height - 30 - $udc, $red); } $lastudc = $udc; } imagepng($image, 'img/data.png'); imagedestroy($image);
return '<p>Leistung in Watt im Verlauf des Tages, Tagesertrag, Temperatur WR, DC-Spannung</p>'; }
-
lasser
- Stammmitglied

-
- Beiträge: 109
- Registriert: 16.04.2010, 10:42
- PV-Anlage [kWp]: 5,5
- Info: Betreiber
Zurück zu Datenlogger
Ähnliche Beiträge
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste
|