Allgemein über Datenlogger, Kommunikation, DFÜ
Moderator: Mod-Team
von [Michi] » 13.10.2012, 17:10
ich habe mal die Werte: Logavginterval=3,Waitinterval=50 in der smw-logger.conf geändert. Jetzt versuch er in die Datenbank zu schreiben. Im Terminalfenster kommt jedoch : root@LINUX:~# /usr/local/bin/smw-logger /usr/local/etc/smw-logger.conf You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1: Success root@LINUX:~# 
-
[Michi]
- Öfters hier

-
- Beiträge: 14
- Registriert: 06.07.2012, 22:22
- Info: Interessent
von sollner11 » 13.10.2012, 17:34
von dem 5-Sekunden-Problem hat solarfan10 schon berichtet: solarfan10 hat geschrieben:erstmal ein Danke an die Ersteller dieses Datenloggers, den ich mittlerweile auch auf meinem Windows-System rudimentär zum Laufen gebracht habe. Und zwar mit einem Solarmax 13MT. Was mich dabei fast zur Verzweiflung gebracht hat, ist die Tatsache, dass das Logger-PHP-Skript und auch nacher das Logger-C-Programm ständig Kommunikationsfehler gemeldet haben. Bis ich dahinter gekommen bin, dass der Solarmax nach knapp 5 Sekunden die Verbindung von sich aus trennt. Just bevor der Logger mit den Standardeinstellungen wieder das nächste Kommando abschickt. Erst als ich dann die Intervallzeit auf 4 Sekunden gedrückt habe, klappte es. (Hattet Ihr mit euren Solarmaxen ähnliche Erfahrungen?) Allerdings hat das den Nachteil, dass dann nur noch der Datenlogger an den Solarmax kommt. Es wird ja scheinbar nur eine Verbindung zu einer Zeit unterstützt. Das möchte ich aber eigentlich gar nicht, ich will auch noch mit der SolarMax-App auf dem iPhone connecten, bzw. mit anderen Datenloggern. Daher denke ich darüber nach, die Verbindung für jede Anfrage vorher aufzubauen und anschließend wieder abzubauen. Da ich den Thread hier noch nicht ganz durch habe, eine Frage an Euch: Hattet Ihr so etwas auch schon versucht? Gab es da Probleme?
und solarfan10 hat geschrieben:ja, die Zeit ist auch bei mir knapp. Ich habe jetzt den logger soweit umgebaut, dass er die Verbindung jedesmal neu aufbaut und dann wieder kappt. Die Schleife habe ich drin gelassen - evtl. muss er ja die db-Verbindung neu aufbauen.
Das Telegramm aus einer meiner letzten Posts hat noch die falsche checksumme, ausserdem musste ich die regex noch anpassen, da die neuen Feldbezeichner teils vierstellig sind. Das läuft auch. Die Db habe ich um einige Felder erweitert. Werde dann noch eine zweite Abfrage für die restlichen Felder programmieren, wenn die Tests für den jetzigen Stand positiv sind.
und zagibu schrieb davon, dass er gar nicht über einen Intervall mithält hast du die Datenbank in der install.sh auch angepasst? (gekürzt) oder muss man das nicht?
-
sollner11
- Fleißiges Mitglied

-
- Beiträge: 456
- Registriert: 05.05.2012, 12:15
- PV-Anlage [kWp]: 19,11
- Info: Betreiber
von zagibu » 14.10.2012, 11:46
Ach so, ja das könnte tatsächlich eines der Probleme sein. Die alten Solarmaxe machen das nämlich nicht, da bleibt die Verbindung offen. Vielleicht mal Solarfan anschreiben für seine modifizierte Version, welche die Verbindung für jede Anfrage neu aufbaut.
Wenn du im debug.log die Meldung "No match" drin hast, dann stimmt das Regex Pattern nicht mit der Antwort überein. Hast du mal geschaut was auf Zeile 23 ist, hast du da wirklich noch ein sprintf drin? Vielleicht fehlt dir auch eine Variablendeklaration.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von [Michi] » 14.10.2012, 19:29
Hallo zagibu, Du hast Recht, der 5 sek Intervall ist das Problem.
Solarfan, kannst Du uns Deine modifizierte Version zur Verfügung stellen ?
Gruss [Michi]
-
[Michi]
- Öfters hier

-
- Beiträge: 14
- Registriert: 06.07.2012, 22:22
- Info: Interessent
von solarfan10 » 15.10.2012, 00:10
Hallo, hab's schon sollner geschrieben - meine Version ist auf C# unter Windows portiert, die habe ich sollner11 auch schon gegeben. Ich selber kann mit dem orignal-code nur unter cygwin compilieren/debuggen und da der cygwin debugger ständig abschmiert, hat mich das so aufgeregt dass ich beschlossen hatte, nach C# zu portieren und dort weiter zu entwickeln. Tut mir leid, aber den Aufwand, zurück zu Linux/C zu gehen, tu ich mir nicht an. Den C#-Code kann ich aber gerne nochmal posten. Prinzipiell ist die Umstellung aber ganz einfach. Michi, Du musst nur die Code-Stelle zum Öffnen der TCP-IP-Verbindung zum Solarmax verschieben, und zwar in die Schleife zum Daten abholen. Ich habe da einiges umgestellt, aber hier das Prinzip: - Code: Alles auswählen
// Open connection if (!open_connection()) { error_retry("ERROR opening connection, retry"); failure_flag = 1; break; }
// Send message 1 if (!SendMessage(message1)) break;
// Read answer 1 string bufferString1 = ReadMessage(); if (bufferString1 == null) break; // error occured during read
string bufferString2 = null; if (isMTseries) { // Send message 2 if (!SendMessage(message2)) break;
// Read answer 2 bufferString2 = ReadMessage(); if (bufferString2 == null) break; // error occured during read }
// and close connection to allow other clients to communicate try { close_connection(); } catch (SocketException) { // ignore socket exceptions on close }
Die Methoden open_connection(), close_connection() und SendMessage() sehen so aus: - Code: Alles auswählen
bool open_connection() {
#if !SIMULATION try { // Try to open socket for communication with solarmax sockfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 0);
// Try to resolve solarmax address/hostname IPAddress[] serverAddresses = Dns.GetHostAddresses(hostaddr);
// Try to establish a connection with solarmax sockfd.Connect(serverAddresses[0], portno);
// Make socket non-blocking set_nonblock(sockfd); } catch(SocketException e) { error_retry(e.Message); Thread.Sleep(60000); // ms return false; }
if (DEBUG) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Connected to solarmax ({0}) on port {1}", hostaddr, portno.ToString()); debug_entry(sb.ToString()); } #endif return true; }
void close_connection() { if (sockfd != null) { sockfd.Shutdown(SocketShutdown.Both); sockfd.Close(); } }
private bool SendMessage(string message1) { if (DEBUG) { debug_entry("Sending message: " + message1); }
// Send message try { #if !SIMULATION byte[] sendBuffer = Encoding.ASCII.GetBytes(message1); int sentBytes = sockfd.Send(sendBuffer); if (sentBytes != message1.Length) { close_connection(); error_retry("ERROR sending TCP packet: " + sentBytes.ToString()); failure_flag = 1; return false; } #endif } catch (SocketException ex) { error_retry(ex.Message); failure_flag = 1; return false; } return true; }
Ist halt alles .NET und C#, aber das Prinzip sollte klar sein. Ihr müsst ja den open/close code nicht auslagern in funktionen, aber halt zumindest vor und nach dem eigentlichen Telegramm-Senden einbauen. Damit die Verbindung nur ganz kurz offen ist. Der code der mit dem define SIMULATION abhängig compiliert wird, ist dazu da, dass ich auch im Dunkeln noch testen kann  . Gerade jetzt ja immer interessanter. bei gesetztem SIMULATION wird nicht kommuniziert und in der Methode ReadMessage dann stattdessen ein Dummy-String zurückgegeben, der ein gültiges Antworttelegramm enthält und den Regexp-Code schön beschäftigt. Hoffe, das hilft euch weiter. Viele Grüße Michael
Jeder fängt mal klein an.
-

solarfan10
- Fleißiges Mitglied

-
- Beiträge: 375
- Registriert: 22.10.2011, 12:48
- PV-Anlage [kWp]: 16,56
- Info: Betreiber
von sollner11 » 16.10.2012, 09:55
danke solarfan10, ich fasse das mal für mich zusammen Erkenntnisse: Die SolarMax MT-Reihe macht es beim Loggen erforderlich, eine Verbindung aufzubauen, die Werte abzufragen, in die DB einzutragen und die Verbindung wieder zu schließen. Die Variablen-Namen sind durch solarfan eigentlich klar. Die machbare Anzahl der Variablen pro Anfrage muss ermittelt werden. Eventuell sind mehrere Anfragen abzusenden. Ein Mitteln von Werten über eine gewisse Zeit ist damit außen vor (bzw. muss vom Viewer gemacht werden) (die Probleme sollten für den Perl-Logger und die C-Varainate von Zagibu gleich gelten) Fragen: In welchem Intervall wird dann überhaupt sinnvoll abgefragt? Ich hatte mal einen thread angefangen, um mir klarzumachen, was alles überhaupt geloggt werden sollte. http://www.photovoltaikforum.com/datenlogger-f5/was-alles-loggen--t83503.htmlDie Auswertung/Visualisierung ist sicher dann sicher auch noch ein Problem, erstmal muss aber der Logger arbeiten. Lösungen: solarfan10 = MT3 = aber mit C## und Windows [Michi] = MT2 = sucht Lösung sollner11 = MT2 = hofft, Michi findet Lösung Gibt es sonst noch wen mit einem MT? Gruss
-
sollner11
- Fleißiges Mitglied

-
- Beiträge: 456
- Registriert: 05.05.2012, 12:15
- PV-Anlage [kWp]: 19,11
- Info: Betreiber
von zagibu » 16.10.2012, 13:08
Wenn ich etwas Zeit habe, werde ich versuchen, den Logger so umzubauen, dass er die Verbindung nach der Abfrage kappt. Ein sinnvolles Log-Intervall ist m.M.n. 1 Minute.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von solarfan10 » 16.10.2012, 13:40
Hallo sollner11,
die Mittelung ist kein Problem. Das Abfrageintervall ist auch kein Problem. Beides bleibt unverändert bestehen. Es ändert sich nur etwas daran, dass die TCP-Verbindung nicht während der ganzen Programmlaufzeit bestehen bleibt, sondern nur kurz, während der eigentlichen Kommunikation. Dazu muss man nur den Verbindungaufbau direkt vor das Telegrammsenden setzen und den Verbindungsabbau (close) halt direkt nach den Empfang. Der Code im Anschluß, also die Mittelung, die Verarbeitung zu SQL, die Wartezeit bis zur nächsten Abfrage, usw., bleiben ja gleich. Eine Mittelung reduziert halt die Datenmenge. Wer genug Platz auf seiner Platte hat und einen Server, der die hohe Datenmenge im Viewer dann auch schnell genug visualisieren kann, kann sicher damit leben. Sinnvoll ist es aus meiner Sicht nicht, da der Viewer ja sowieso nur eine horizontale Auflösung von maximal 1 Minute hat (im Standardfall). Die Zwischenwerte fallen damit sowieso unter den Tisch. Womit aus meiner Sicht die sinnvolle Abfragezeit durchaus 5s mit Mittelung bei 1min sein kann.
Viele Grüße Michael
Jeder fängt mal klein an.
-

solarfan10
- Fleißiges Mitglied

-
- Beiträge: 375
- Registriert: 22.10.2011, 12:48
- PV-Anlage [kWp]: 16,56
- Info: Betreiber
von zagibu » 17.10.2012, 14:50
Ich glaube, die Mittelung wurde vor allem eingebaut, weil man keine ausgefranste Kurve sehen wollte im Diagramm.
-
zagibu
- Vielschreiber

-
- - Threadstarter -
-
- Beiträge: 195
- Registriert: 27.07.2010, 16:31
- PV-Anlage [kWp]: 3
- Info: Betreiber
von sollner11 » 17.10.2012, 15:15
hallo, inzwischen loggt er, ... mit anpassungen von mich hier mal meine Dateien: smw-logger.c - Code: Alles auswählen
/* Simple solarmax logger c program written by zagibu@gmx.ch in July 2010 This program was originally licensed under WTFPL 2 http://sam.zoy.org/wtfpl/ It is now licensed under GPLv2 or later http://www.gnu.org/licenses/gpl2.html
You need the mysql client library files installed to be able to compile it.
Compile with: gcc -W -Wall -Wextra -Wshadow -Wlong-long -Wformat -Wpointer-arith -rdynamic -pedantic-errors -std=c99 -o smw-logger smw-logger.c -lmysqlclient
Run with: ./smw-logger /path/to/config-file
Structure of the config-file:
Debug=0 Loginterval=60 Waitinterval=200 DBhost=localhost DBname=solarmax DBtabprefix=log DBuser=solaruser DBpass=userpassword Hostname=192.168.178.35 Hostport=12345 NumberOfInverters=1
You can set DEBUG to 1 to get detailed output in a separate logfile.
It is recommended to schedule the smw-logger to be started between 5:00 - 6:00 in the morning and stopped between 22:00 and 23:00 in the evening (compare with sunshine duration). The smw-logger has no built-in facility for logging, so use CRON or similar.
Example CRON entries: 00 05 * * * /usr/local/bin/smw-logger /usr/local/etc/smw-logger.conf 00 23 * * * killall smw-logger
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> #include <pthread.h>
FILE* error_file = NULL; char error_file_name[512]; char* error_mode = "w"; FILE* debug_file = NULL; char debug_file_name[512]; char* debug_mode = "w"; FILE* config_file = NULL; char* config_file_name; char* config_mode = "r"; int sockfd, portno, n, log_interval, logavg_interval, result, counter, wait_interval, active_max, nr_of_maxes, DEBUG; // Renamed this flag because it is used for connection and regexp problems int failure_flag = 0; struct sockaddr_in serv_addr; struct hostent* server; char dbhost[512]; char dbname[512]; char dbtabprefix[512]; char dbuser[512]; char dbpass[512]; char hostaddr[512]; char line[512]; char* message; 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]*)";
int kdy, kmt, kyr, kt0, tnf, tkk, pac, ud01, ud02, id01, id02, sys; char buffer[512], buffer2[512]; char query[512]; char* temp; regex_t rx; regmatch_t* matches; MYSQL* connection = NULL; // average stuff vars int i;
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[]) { // Hold the time to wait between single requests. //int logavg_interval = 5;
// Check commandline arguments if (argc < 2) error_exit("ERROR program needs config-file as parameter");
//Read Config File config_file_name = argv[1]; FILE *fp = fopen(config_file_name, config_mode);
// Read variables if (fp) { while (fgets(line, sizeof(line), fp)) { sscanf(line, "Debug=%d[^\n]", &DEBUG); sscanf(line, "Errorfile=%[^\n]", error_file_name); sscanf(line, "Debugfile=%[^\n]", debug_file_name); sscanf(line, "Loginterval=%d[^\n]", &log_interval); sscanf(line, "Logavginterval=%d[^\n]", &logavg_interval); sscanf(line, "Waitinterval=%d[^\n]", &wait_interval); sscanf(line, "DBhost=%[^\n]", dbhost); sscanf(line, "DBname=%[^\n]", dbname); sscanf(line, "DBtabprefix=%[^\n]", dbtabprefix); sscanf(line, "DBuser=%[^\n]", dbuser); sscanf(line, "DBpass=%[^\n]", dbpass); sscanf(line, "Hostname=%[^\n]", hostaddr); sscanf(line, "Hostport=%d[^\n]", &portno); sscanf(line, "NumberOfInverters=%d[^\n]", &nr_of_maxes); } } fclose(fp);
// 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);
// create the arrays for the average calculation long tkdy[nr_of_maxes], tkmt[nr_of_maxes], tkyr[nr_of_maxes], tkt0[nr_of_maxes], ttnf[nr_of_maxes], ttkk[nr_of_maxes], tpac[nr_of_maxes], tud01[nr_of_maxes], tud02[nr_of_maxes], tid01[nr_of_maxes], tid02[nr_of_maxes], tsys[nr_of_maxes]; // calculate the requests per log_interval // TODO -2 is a dirty fix to avoid desync int logavg_pertick = (int)((log_interval-2)/logavg_interval);
// 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); }
// 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) {
// set variable to default value or it will keep trying to reconnect failure_flag = 0;
// Check if connection to db-server must be re-established if (mysql_ping(connection)) {
//TODO Maybe a reconnect (if needed) here ? // 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(hostaddr); if (server == NULL) { sprintf(buffer, "Can't resolve \"%s\"", hostaddr); 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), hostaddr, 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", hostaddr, portno); debug_entry(buffer); }
// Start sending the data requests and logging the answers while (1) { time_t start_time = time(NULL); for (i = 0; i < nr_of_maxes; ++i) { tkdy[i] = tkmt[i] = tkyr[i] = tkt0[i] = ttnf[i] = ttkk[i] = tpac[i] = tud01[i] = tud02[i] = tid01[i] = tid02[i] = tsys[i] = 0; }
// Get the current time for (i = 0; i < logavg_pertick; ++i) { time_t single_start_time = time(NULL); // We have to get out of this while-loop to reestablish the connection to the inverter if (failure_flag == 1){ debug_entry("Looks like we lost our connection to solarmax, reconnecting..."); break; }
for(active_max = 1; active_max <= nr_of_maxes; active_max++){
// Generate message according to device address of solarmax:
// Could be something like this: // sprintf(message, "{FB;0%d;46|64:KDY;KMT;KYR;KT0;TNF;TKK;PAC;PRL;IL1;IDC;UL1;UDC;SYS|%s}", active_max, 16_bit_checksum // For further information on the protocol refer to: http://blog.dest-unreach.be/2009/04/15/solarmax-maxtalk-protocol-reverse-engineered
// Until someone comes up with a nice solution to calculate the checksum, lets stick to a few precalculated message strings (tested only for 2 maxes!): if (active_max == 1) { message = "{FB;01;46|64:KDY;KMT;KYR;KT0;TNF;TKK;PAC;UD01;UD02;ID01;ID02;SYS|10fe}"; }
// Send message n = write(sockfd,message,strlen(message)); usleep(100000); debug_entry(buffer); if (n < 0) { close(sockfd); error_retry("ERROR sending TCP packet"); failure_flag = 1; break; }
// Read answer bzero(buffer, 256); n = read(sockfd, buffer, 255); for (counter = 0; counter < wait_interval && n < 0; counter++) { if (DEBUG) debug_entry("Socket contains no data, trying to read again later"); debug_entry(buffer); usleep(10000); n = read(sockfd, buffer, 255); }
if (n < 0) { close(sockfd); error_retry("ERROR receiving TCP packet"); failure_flag = 1; 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)); debug_entry(buffer); //error_exit("ERROR no regexp match"); error_retry("ERROR no regexp match!"); // TODO Create flag for this kind of failure or rename this one failure_flag = 2; break; }
// 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); ttnf[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so); ttkk[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so); tpac[active_max-1] += strtol(temp, NULL, 16) / 2; free(temp); temp = strndup(buffer + matches[8].rm_so, matches[8].rm_eo - matches[8].rm_so); tud01[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[9].rm_so, matches[9].rm_eo - matches[9].rm_so); tud02[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[10].rm_so, matches[10].rm_eo - matches[10].rm_so); tid01[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[11].rm_so, matches[11].rm_eo - matches[11].rm_so); tid02[active_max-1] += strtol(temp, NULL, 16); free(temp); temp = strndup(buffer + matches[12].rm_so, matches[12].rm_eo - matches[12].rm_so); tsys[active_max-1] += strtol(temp, NULL, 16); //sys = strtol(temp, NULL, 16); free(temp); } if (failure_flag > 0){ break; } //TODO check if the task need more time than logavg_interval sleep(logavg_interval - (time(NULL)-single_start_time)); } // Calculate the average values and insert into db if (failure_flag == 0){ for (i = 0; i < nr_of_maxes; ++i) { tkdy[i] = (int)((tkdy[i]*1.0)/(logavg_pertick*1.0)); tkmt[i] = (int)((tkmt[i]*1.0)/(logavg_pertick*1.0)); tkyr[i] = (int)((tkyr[i]*1.0)/(logavg_pertick*1.0)); tkt0[i] = (int)((tkt0[i]*1.0)/(logavg_pertick*1.0)); ttnf[i] = (int)((ttnf[i]*1.0)/(logavg_pertick*1.0)); ttkk[i] = (int)((ttkk[i]*1.0)/(logavg_pertick*1.0)); tpac[i] = (int)((tpac[i]*1.0)/(logavg_pertick*1.0)); tud01[i] = (int)((tud01[i]*1.0)/(logavg_pertick*1.0)); tud02[i] = (int)((tud02[i]*1.0)/(logavg_pertick*1.0)); tid01[i] = (int)((tid01[i]*1.0)/(logavg_pertick*1.0)); tid02[i] = (int)((tid02[i]*1.0)/(logavg_pertick*1.0)); tsys[i] = (int)((tsys[i]*1.0)/(logavg_pertick*1.0));
// Construct the query according to active solarmax sprintf(query, "INSERT INTO %s%d (kdy, kmt, kyr, kt0, tnf, tkk, pac, ud01, ud02, id01, id02, sys) VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d);", dbtabprefix, (i+1), kdy, kmt, kyr, kt0, (int)ttnf[i], (int)ttkk[i], (int)tpac[i], (int)tud01[i], (int)tud02[i], (int)tid01[i], (int)tid02[i], 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 - calc duration - 1 if (DEBUG) debug_entry("Waiting for about 1 minute ..."); // Get the current time time_t stop_time = time(NULL); // TODO check if time needed is > log_interval int sleepTime = log_interval + start_time - stop_time - 1; if(sleepTime > 0) sleep(sleepTime); else{ sprintf(buffer, "!!! sleepTime error. Assuming desync: %i seconds. !!!\n", sleepTime); debug_entry(buffer); }
// Add a busy-loop for the last second to make sure we are perfectly accurate while (time(NULL) < start_time + log_interval) usleep(99999);
// If the connection is lost -> retry if (failure_flag == 1){ // just to be sure close(sockfd); break; } } } return 0; }
root@raspberrypi:/usr/local/etc# cat smw-logger.conf - Code: Alles auswählen
# Settings for the Solarmax Watcher # defaults are shown in parentheses
## Global settings of the logger
# Debug? (0) Debug=1
# location of error file Errorfile=/var/log/solarmax-error.log
# location of logging file Debugfile=/var/log/solarmax-debug.log
# Interval to read the values of the inverter (60) Loginterval=60
# Interval between the queries for the averageable values during this # interval (5). This means that the values will be averaged about # Loginterval/Logavginterval (12) times during one Loginterval. Logavginterval=3
# Interval to wait for inverters answer (200) Waitinterval=50
## MySQL settings
# Hostname which is running the MySQL server (localhost) DBhost=localhost
# Name of the MySQL DB for the Solarmax logger (solarmax) DBname=solarmax
# Tablename prefix (log) DBtabprefix=log
# DB user to write the values solarmax-DB (solaruser) DBuser=solaruser
# Password for the DB user (userpassword) DBpass=solarpi39
## Inverter settings
# IP-address or hostname of the inverter (192.168.178.35) Hostname=192.168.178.90
# IP-Port of the inverter (12345) Hostport=12345
# Number of Solarmax inverters in your array (1) NumberOfInverters=1
der Zusammenhang von: Loginterval=60 Logavginterval=3 Waitinterval=50 erschliesst sich mir noch nicht richtig fakt ist, dass er anfangs alle 1,5 min in die DB einträgt und dann später irgendwann alle 3 min gibt es da eine Logik? offensichtlich nimmt er aber die 12 Variablen in einem Zug Gruss
-
sollner11
- Fleißiges Mitglied

-
- Beiträge: 456
- Registriert: 05.05.2012, 12:15
- PV-Anlage [kWp]: 19,11
- Info: Betreiber
Zurück zu Datenlogger
Ähnliche Beiträge
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste
|