From 352e7907063d14bab9e0888ff709f3210814a937 Mon Sep 17 00:00:00 2001 From: eddyem Date: Thu, 21 Nov 2019 20:07:35 +0300 Subject: [PATCH] Seems like it works! --- src/netdaemon/cmdlnopts.c | 1 + src/netdaemon/cmdlnopts.h | 1 + src/netdaemon/datapoints.xy | 72 --------------- src/netdaemon/gnuplot.c | 37 ++++---- src/netdaemon/main.c | 41 +++++++-- src/netdaemon/plot | 2 +- src/netdaemon/sens_place.c | 15 ++-- src/netdaemon/socket.c | 48 ++++++---- src/netdaemon/socket.h | 2 + src/netdaemon/tempadj.txt | 5 -- src/netdaemon/term.c | 8 +- src/netdaemon/term.h | 10 ++- src/netdaemon/usefull_macros.c | 157 +++++++++++++++++++++++++++++++-- src/netdaemon/usefull_macros.h | 19 ++-- 14 files changed, 266 insertions(+), 152 deletions(-) delete mode 100644 src/netdaemon/datapoints.xy diff --git a/src/netdaemon/cmdlnopts.c b/src/netdaemon/cmdlnopts.c index 974f515..729920a 100644 --- a/src/netdaemon/cmdlnopts.c +++ b/src/netdaemon/cmdlnopts.c @@ -66,6 +66,7 @@ myoption cmdlnopts[] = { {"testadjfile",NO_ARGS, NULL, 'T', arg_int, APTR(&G.testadjfile),_("test format of file with T adjustements and force running proces to re-read it")}, {"adjname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.adjfilename),_("name of adjustements file (default: tempadj.txt)")}, {"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfilename),_("name of PID file (default: " DEFAULT_PIDFILE ")")}, + {"dumpoff", NO_ARGS, NULL, 'd', arg_string, APTR(&G.dumpoff), _("dump sensors data & turn all OFF until next request")}, end_option }; diff --git a/src/netdaemon/cmdlnopts.h b/src/netdaemon/cmdlnopts.h index 556e910..cac1130 100644 --- a/src/netdaemon/cmdlnopts.h +++ b/src/netdaemon/cmdlnopts.h @@ -40,6 +40,7 @@ typedef struct{ int testadjfile; // test format of file with adjustments char *adjfilename; // name of adjustements file char *pidfilename; // name of PID file + int dumpoff; // dump sensors data & turn all OFF until next request } glob_pars; diff --git a/src/netdaemon/datapoints.xy b/src/netdaemon/datapoints.xy deleted file mode 100644 index cd481a4..0000000 --- a/src/netdaemon/datapoints.xy +++ /dev/null @@ -1,72 +0,0 @@ -/* - * geany_encoding=koi8-r - * datapoints.xy - coordinates of sensors - * - * Copyright 2018 Edward V. Emelianov - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -/** - * Unload# X,dm Y,dm Controller# Sensors Pair# - * 3 -3 -5 4 0 - * 6 3 5 2 0 - * 7 13 -4 1 0 - * 9 3 -13 1 1,2 - * 11 -9 -9 4 1 - * 13 -13 4 3 0 - * 15 -3 13 3 1,2 - * 17 9 9 2 1 - * 21 15 -12 1 3 - * 24 -3 -20 4 2 - * 27 -18 -7 3 3 - * 30 -15 12 3 4 - * 33 3 20 2 2 - * 36 18 7 2 3 - * 38 25 -10 1 4 - * 40 16 -21 1 5 - * 42 4 -26 4 3 - * 44 -11 -25 4 4 - * 46 -21 -17 4 5 - * 48 -26 -5 3 5 - * 50 -25 10 3 6 - * 52 -16 21 3 7 - * 54 -4 26 2 4 - * 56 11 25 2 5 - * 58 21 17 2 6 - * 60 26 5 1 6 - */ - -// sensors groups coordinates: [Nsensor][Ncontroller][xy] -const int SensCoords[8][8][2] = { - // sensor 0, unloads: none,7,6,13,3 - {{0,0},{13,-4},{3,5},{-13,4},{-3,-5}}, - // sensor 1, unloads: none,9,17,15,11 - {{0,0},{3,-13},{9,9},{-3,13},{-9,-9}}, - // sensor 2, unloads: none,9,33,15,24 - {{0,0},{3,-13},{3,20},{-3,13},{-3,-20}}, - // sensor 3, unloads: none,21,36,27,42 - {{0,0},{15,-12},{18,7},{-18,-7},{4,-26}}, - // sensor 4, unloads: none,38,54,30,44 - {{0,0},{25,-10},{-4,26},{-15,12},{-11,-25}}, - // sensor 5, unloads: none,40,56,48,46 - {{0,0},{16,-21},{11,25},{-26,-5},{-21,-17}}, - // sensor 6, unloads: none,60,58,50 - {{0,0},{26,5},{21,17},{-25,10}}, - // sensor 7, unloads: none,none,none,52 - {{0,0},{0,0},{0,0},{-16,21}}, -}; diff --git a/src/netdaemon/gnuplot.c b/src/netdaemon/gnuplot.c index 84f3a76..5428909 100644 --- a/src/netdaemon/gnuplot.c +++ b/src/netdaemon/gnuplot.c @@ -21,9 +21,10 @@ * */ #include // file operations +#include #include // access() to check file exists #include // PATH_MAX -#include "usefull_macros.h" // putlog +#include "usefull_macros.h" #include "cmdlnopts.h" // glob_pars extern glob_pars *G; @@ -32,6 +33,7 @@ static char fullpath[PATH_MAX]; // create full name from path and file char *mkname(char *path, char *fname){ + if(!path) return fname; if(path[strlen(path)-1] == '/') snprintf(fullpath, PATH_MAX, "%s%s", path, fname); else snprintf(fullpath, PATH_MAX, "%s/%s", path, fname); DBG("fullpath: %s", fullpath); @@ -48,6 +50,7 @@ char *mkname(char *path, char *fname){ static int formfile(char *fname, double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], int Z){ FILE *F = fopen(fname, "w"); if(!F) return 0; + int nonzero_values = 0; for(int i = 1; i <= NCTRLR_MAX; ++i){ for(int N = 0; N <= NCHANNEL_MAX; ++ N) for(int p = 0; p < 2; ++p){ double T = data[p][N][i]; @@ -56,10 +59,12 @@ static int formfile(char *fname, double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], i if(!sdata) continue; if(Z != sdata->Z) continue; fprintf(F, "%d\t%d\t%.2f\n", sdata->X, sdata->Y, T - sdata->dt - sdata->Tadj); + ++nonzero_values; } } } fclose(F); + if(!nonzero_values) return 0; DBG("File %s ready", fname); return 1; } @@ -71,42 +76,30 @@ static int formfile(char *fname, double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], i */ static void gnuplot(char *path, char *fname){ char *ctmp = mkname(path, "plot"); - char buf[PATH_MAX*2]; + char buf[PATH_MAX*2], *ptr = buf; size_t L = PATH_MAX*2; if(access(ctmp, F_OK)){ WARNX(_("Don't find %s to plot graphics"), ctmp); - putlog("Don't find %s to plot graphics", ctmp); return; } - ssize_t l = snprintf(buf, L, "%s ", ctmp); + ssize_t l = snprintf(ptr, L, "%s ", ctmp); if(l < 1) return; + L -= l; ptr += l; ctmp = mkname(path, fname); - snprintf(buf+l, L, "%s", ctmp); + time_t t = time(NULL); + struct tm *timeptr = localtime(&t); + l = snprintf(ptr, L, "%s ", ctmp); + L -= l; ptr += l; + strftime(ptr, L, "\"%d/%m/%y %H:%M:%S\"", timeptr); DBG("Run %s", buf); if(system(buf)){ WARNX(_("Can't run `%s`"), buf); - putlog("Can't run `%s`", buf); - } + }else putlog("created chart %s", fname); } void plot(double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], char *savepath){ - /* - double dY[NCH][NC]; // vertical gradients (top - bottom) - // calculate gradients - for(int i = 1; i < 8; ++i){ - for(int N = 0; N < 8; ++ N){ - double Ttop = data[0][N][i], Tbot = data[1][N][i]; - if(Ttop > -100. && Ttop < 100. && Tbot > -100. && Tbot < 100.){ - double dT = Ttop - Tbot; - if(dT > -2. && dT < 2.) dY[N][i] = dT; - else dY[N][i] = -300.; - }else dY[N][i] = -300.; - } - }*/ char *ctmp = mkname(savepath, "T0"); if(formfile(ctmp, data, 0)) if(G->makegraphs) gnuplot(savepath, "T0"); ctmp = mkname(savepath, "T1"); if(formfile(ctmp, data, 1)) if(G->makegraphs) gnuplot(savepath, "T1"); - //ctmp = mkname(savepath, "Tgrad"); - //if(formfile(ctmp, dY)) if(G->makegraphs) gnuplot(savepath, "Tgrad"); } diff --git a/src/netdaemon/main.c b/src/netdaemon/main.c index a1b730a..3f348c9 100644 --- a/src/netdaemon/main.c +++ b/src/netdaemon/main.c @@ -24,6 +24,7 @@ #include "checkfile.h" #include "cmdlnopts.h" #include "socket.h" +#include "term.h" #include "usefull_macros.h" glob_pars *G; // non-static: some another files should know about it! @@ -33,12 +34,22 @@ static pid_t childpid = 0; // PID of child - to kill it if need void signals(int signo){ restore_console(); restore_tty(); - putlog("exit with status %d", signo); + if(childpid){ + const char *s = signum_to_signame(signo); + if(s) putlog("exit with status %d (or by signal %s)", signo, s); + else putlog("exit with status %d", signo); + } exit(signo); } +// report about some ignored signals +static void repsig(int signo){ + const char *s = signum_to_signame(signo); + WARNX("PID: %d, received signal %d, %s (%s)", getpid(), signo, s ? s : "", strsignal(signo)); +} + // SIGUSR1 handler - re-read Tadj file -void refreshAdj(_U_ int signo){ +static void refreshAdj(_U_ int signo){ DBG("refresh adj"); if(childpid){ // I am a master putlog("Force child %d to re-read adj-file", childpid); @@ -49,6 +60,15 @@ void refreshAdj(_U_ int signo){ } } +static void logT(_U_ int signo){ + for(int i = 0; i < 3; ++i){ + const char *s = gotstr(i); + if(s && *s) putlog("Sensors group #%d:\n%s", i, s); + } + putlog("Turn sensors off"); + TurnOFF(); +} + int main(int argc, char **argv){ initial_setup(); G = parse_args(argc, argv); @@ -57,9 +77,13 @@ int main(int argc, char **argv){ if(G->makegraphs && !G->savepath){ ERRX(_("Point the path to graphical files")); } - DBG("t=%d", G->testadjfile); - int raf = read_adj_file(G->adjfilename); pid_t runningproc = check4running(G->pidfilename); + if(G->dumpoff){ + if(runningproc) kill(runningproc, SIGUSR2); + else ERRX("There's no running daemon"); + return 0; + } + int raf = read_adj_file(G->adjfilename); if(G->testadjfile){ if(raf == 0){ green("Format of file %s is right\n", G->adjfilename); @@ -71,12 +95,16 @@ int main(int argc, char **argv){ return 1; } if(runningproc) ERRX("Found running process, pid=%d.", runningproc); + // ignore almost all possible signals + for(int sig = 0; sig < 256; ++sig) signal(sig, repsig); signal(SIGTERM, signals); // kill (-15) - quit signal(SIGHUP, SIG_IGN); // hup - ignore + signal(SIGCHLD, SIG_DFL); // chld - default signal(SIGINT, signals); // ctrl+C - quit signal(SIGQUIT, signals); // ctrl+\ - quit signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z signal(SIGUSR1, refreshAdj); // refresh adjustements + signal(SIGUSR2, logT); // print all current temperatures into logfile and turn off sensors #ifndef EBUG if(!G->terminal){ if(daemon(1, 0)){ @@ -87,10 +115,9 @@ int main(int argc, char **argv){ if(childpid){ putlog("create child with PID %d\n", childpid); DBG("Created child with PID %d\n", childpid); - wait(NULL); - putlog("child %d died\n", childpid); + while(childpid != waitpid(childpid, NULL, 0)); WARNX("Child %d died\n", childpid); - sleep(1); + sleep(10); }else{ prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies break; // go out to normal functional diff --git a/src/netdaemon/plot b/src/netdaemon/plot index 57d151d..d9990f2 100755 --- a/src/netdaemon/plot +++ b/src/netdaemon/plot @@ -32,7 +32,7 @@ set xrange [-30:30] set yrange [-30:30] set xlabel "X, dm" set ylabel "Y, dm" -set title "Mirror temperature" +set title "Mirror temperature $2" set pm3d map unset key circle(x,y,z) = x**2+y**2 > 900 ? NaN : z diff --git a/src/netdaemon/sens_place.c b/src/netdaemon/sens_place.c index 26bc19f..11c9a5b 100644 --- a/src/netdaemon/sens_place.c +++ b/src/netdaemon/sens_place.c @@ -202,14 +202,15 @@ const sensor_data *get_sensor_location(int Nct, int Nch, int Ns){ return NULL; } int idx = 2*(NCHANNEL_MAX+1)*(Nct - 1) + 2*Nch + Ns; - DBG("Sensor code %d%d%d (idx=%d):\n", Nct, Nch, Ns, idx); + //DBG("Sensor code %d%d%d (idx=%d):\n", Nct, Nch, Ns, idx); const sensor_data *s = sensors + idx; - DBG("\tdT=%g (adj:%g); coords=(%d, %d, %d)\n", s->dt, s->Tadj, s->X, s->Y, s->Z); + //DBG("\tdT=%g (adj:%g); coords=(%d, %d, %d)\n", s->dt, s->Tadj, s->X, s->Y, s->Z); return s; } // return next non-space character in line until first '\n' or NULL if met '#' or '\n' static char *omitspaces(char *str){ + if(!str) return NULL; char ch; do{ ch = *str; @@ -243,7 +244,6 @@ int read_adj_file(char *fname){ mmapbuf *buf = My_mmap(fname); if(!buf) return 1; char *adjf = buf->data, *eof = adjf + buf->len; - DBG("buf: %s", adjf); int strnum = 1; // start string number from 1 while(adjf < eof){ char *eol = strchr(adjf, '\n'); @@ -251,24 +251,20 @@ int read_adj_file(char *fname){ if(!nextchar){ goto cont; } - DBG("First char: %c", *nextchar); char *endptr = NULL; long num = strtol(nextchar, &endptr, 10); if(endptr == nextchar || !endptr){ WARNX("Wrong integer number!"); goto reperr; } - DBG("first num: %ld", num); int Nctrl = num / 100; int Nch = (num - Nctrl*100) / 10; int Nsen = num%10; - DBG("Nc=%d, Nch=%d, NS=%d", Nctrl, Nch, Nsen); if(num < 0 || (Nsen != 0 && Nsen != 1) || (Nch < 0 || Nch > NCHANNEL_MAX) || (Nctrl < 1 || Nctrl > NCTRLR_MAX)){ WARNX("Wrong sensor number: %ld", num); goto reperr; } int idx = 2*(NCHANNEL_MAX+1)*(Nctrl - 1) + 2*Nch + Nsen; - DBG("index: %d", idx); if(idx < 0 || idx > NSENSORS-1){ WARNX("Sensor index (%d) over range 0..%d", idx, NSENSORS-1); } @@ -282,7 +278,6 @@ int read_adj_file(char *fname){ WARNX("Wrong double number!"); goto reperr; } - DBG("double num: %g", t); Tadj[idx] = t; if(omitspaces(endptr)){ WARNX("Wrong file format: each string should include two numbers (and maybe comment after #)"); @@ -294,10 +289,12 @@ cont: ++strnum; } My_munmap(buf); + printf("Non-zero components:\n"); for(int i = 0; i < NSENSORS; ++i){ if(fabs(Tadj[i]) > DBL_EPSILON){ - printf("Tadj[%d] = %g\n", i, Tadj[i]); + printf("\tTadj[%02d] = %g\n", i, Tadj[i]); } + if(fabs(sensors[i].Tadj - Tadj[i]) > 0.001) putlog("Tadj[%d] = %g", i, Tadj[i]); sensors[i].Tadj = Tadj[i]; } return 0; diff --git a/src/netdaemon/socket.c b/src/netdaemon/socket.c index ebd9201..131874c 100644 --- a/src/netdaemon/socket.c +++ b/src/netdaemon/socket.c @@ -46,6 +46,16 @@ static double meanT; extern glob_pars *G; +// turn off sensors after measurements request or right now +static bool TurnOff = FALSE; +void TurnOFF(){TurnOff = TRUE;} + +// return pointer to strT[N] +const char *gotstr(int N){ + if(N < 0 || N > 2) return NULL; + return strT[N]; +} + /**************** COMMON FUNCTIONS ****************/ /** * wait for answer from socket @@ -121,6 +131,7 @@ static int send_data(int sock, int webquery, int Nsens){ // search a first word after needle without spaces static char* stringscan(char *str, char *needle){ + if(!str || !needle) return NULL; char *a, *e; char *end = str + strlen(str); a = strstr(str, needle); @@ -134,8 +145,8 @@ static char* stringscan(char *str, char *needle){ } static void *handle_socket(void *asock){ - //putlog("handle_socket(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); FNAME(); + if(!asock) return NULL; int sock = *((int*)asock); int webquery = 0; // whether query is web or regular char buff[BUFLEN]; @@ -147,13 +158,10 @@ static void *handle_socket(void *asock){ continue; } if(!(rd = read(sock, buff, BUFLEN-1))){ - //putlog("socket closed. Exit"); break; } - //putlog("client send %zd bytes", rd); DBG("Got %zd bytes", rd); if(rd < 0){ // error - //putlog("some error occured"); DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); break; } @@ -181,24 +189,21 @@ static void *handle_socket(void *asock){ char tbuf[10]; ssize_t L = snprintf(tbuf, 10, "%.2f", meanT); if(L != write(sock, tbuf, L)) WARN("write()"); - //DBG("Ask Tmean = %g", meanT); } // here can be more parsers break; } close(sock); - //DBG("closed"); - //putlog("socket closed, exit"); pthread_exit(NULL); return NULL; } // main socket server static void *server(void *asock){ - putlog("server(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); + if(!asock) return NULL; + //putlog("server(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); int sock = *((int*)asock); if(listen(sock, BACKLOG) == -1){ - putlog("listen() failed"); - WARN("listen"); + WARN("listen()"); return NULL; } while(1){ @@ -208,7 +213,6 @@ static void *server(void *asock){ if(!waittoread(sock)) continue; newsock = accept(sock, (struct sockaddr*)&their_addr, &size); if(newsock <= 0){ - putlog("accept() failed"); WARN("accept()"); continue; } @@ -220,7 +224,6 @@ static void *server(void *asock){ red("Got connection from %s\n", str); pthread_t handler_thread; if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ - putlog("server(): pthread_create() failed"); WARN("pthread_create()"); }else{ DBG("Thread created, detouch"); @@ -323,6 +326,7 @@ static void process_T(){ } // make graphics if(G->savepath){ + DBG("GOT %dTH MEAN DATA", Nmeanmax+1); if(++Nmeanmax == GRAPHS_AMOUNT){ for(i = 1; i <= NCTRLR_MAX; ++i)for(N = 0; N <= NCHANNEL_MAX; ++ N)for(p = 0; p < 2; ++p){ if(Nmean[p][N][i]){ @@ -331,7 +335,9 @@ static void process_T(){ }else Tmean[p][N][i] = -300.; // no data } plot(Tmean, G->savepath); + DBG("memset start"); memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1)); + DBG("memset end"); Nmeanmax = 0; } } @@ -344,21 +350,27 @@ static void daemon_(int sock){ if(sock < 0) return; pthread_t sock_thread; if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ - putlog("daemon_(): pthread_create() failed"); ERR("pthread_create()"); } - double tgot = 0.; + double tgot = 0., tlastoff = dtime(); do{ if(pthread_kill(sock_thread, 0) == ESRCH){ // died WARNX("Sockets thread died"); - putlog("Sockets thread died"); pthread_join(sock_thread, NULL); if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ - putlog("daemon_(): new pthread_create() failed"); ERR("pthread_create()"); } } usleep(1000); // sleep a little or thread's won't be able to lock mutex + if(TurnOff){ + TurnOff = FALSE; + turn_all_off(); + tlastoff = dtime(); + } + if(dtime() - tlastoff > T_OFF_INTERVAL){ + turn_all_off(); + tlastoff = dtime(); + } if(dtime() - tgot < T_INTERVAL) continue; // get data int i; @@ -407,6 +419,7 @@ static void daemon_(int sock){ * Run daemon service */ void daemonize(char *port){ + if(!port) return; FNAME(); int sock = -1; struct addrinfo hints, *res, *p; @@ -439,14 +452,13 @@ void daemonize(char *port){ break; // if we get here, we have a successfull connection } if(p == NULL){ - putlog("failed to bind socket, exit"); // looped off the end of the list with no successful bind ERRX("failed to bind socket"); } freeaddrinfo(res); daemon_(sock); close(sock); - putlog("socket closed, exit"); + putlog("daemonize(): UNREACHABLE CODE REACHED!"); signals(0); } diff --git a/src/netdaemon/socket.h b/src/netdaemon/socket.h index 3cf62c4..1672b94 100644 --- a/src/netdaemon/socket.h +++ b/src/netdaemon/socket.h @@ -28,5 +28,7 @@ #define SOCKET_TIMEOUT (5.0) void daemonize(char *port); +const char *gotstr(int N); +void TurnOFF(); #endif // __SOCKET_H__ diff --git a/src/netdaemon/tempadj.txt b/src/netdaemon/tempadj.txt index cb482e1..29def47 100644 --- a/src/netdaemon/tempadj.txt +++ b/src/netdaemon/tempadj.txt @@ -1,6 +1 @@ #No dT (Treal = T - dT) -100 -0.02 -101 3. -# some more comments - 560 -0.06 # another comment -571 -0.01 # test diff --git a/src/netdaemon/term.c b/src/netdaemon/term.c index 48796e8..b19c0b3 100644 --- a/src/netdaemon/term.c +++ b/src/netdaemon/term.c @@ -209,7 +209,13 @@ int poll_sensors(int N){ return 1; } - +/** + * @brief turn_all_off - turn all sensors OFF + */ +void turn_all_off(){ + send_cmd(0, CMD_SENSORS_OFF_LOCAL); + for(int i = 1; i <= NCTRLR_MAX; ++i) send_cmd(i, CMD_SENSORS_OFF); +} /** * check whether connected device is main Thermal controller diff --git a/src/netdaemon/term.h b/src/netdaemon/term.h index e8e7a0f..f5dd504 100644 --- a/src/netdaemon/term.h +++ b/src/netdaemon/term.h @@ -24,21 +24,22 @@ #include "sens_place.h" // NCTRLR -#define FRAME_MAX_LENGTH (300) -#define MAX_MEMORY_DUMP_SIZE (0x800 * 4) // Terminal timeout (seconds) #define WAIT_TMOUT (0.5) // Main controller polling timeout - 1 second #define POLLING_TMOUT (1.0) // Thermal polling timeout: 5 seconds #define T_POLLING_TMOUT (5.0) -// T measurement time interval - 1 minute -#define T_INTERVAL (60.0) +// T measurement time interval - 30 seconds +#define T_INTERVAL (30.0) +// Interval of turning sensors off - 3 days +#define T_OFF_INTERVAL (259200.) // amount of measurement to plot mean graphs #define GRAPHS_AMOUNT (15) // Protocol #define CMD_SENSORS_OFF 'F' +#define CMD_SENSORS_OFF_LOCAL 'f' #define CMD_VOLTAGE 'K' #define CMD_PING 'P' #define CMD_MEASURE_T 'T' @@ -59,5 +60,6 @@ void run_terminal(); void try_connect(char *device); int poll_sensors(int N); int check_sensors(); +void turn_all_off(); #endif // __TERM_H__ diff --git a/src/netdaemon/usefull_macros.c b/src/netdaemon/usefull_macros.c index 30f07ab..460c68c 100644 --- a/src/netdaemon/usefull_macros.c +++ b/src/netdaemon/usefull_macros.c @@ -22,6 +22,7 @@ #include "usefull_macros.h" #include #include // PATH_MAX +#include /** * function for different purposes that need to know time intervals @@ -286,7 +287,7 @@ void restore_tty(){ } #ifndef BAUD_RATE -#define BAUD_RATE B4800 +#define BAUD_RATE B9600 #endif // init: void tty_init(char *comdev){ @@ -343,10 +344,11 @@ size_t read_tty(char *buff, size_t length){ // wait for 100ms tv.tv_sec = 0; tv.tv_usec = 100000; retval = select(comfd + 1, &rfds, NULL, NULL, &tv); - if (!retval) break; + if (retval < 1) break; // retval == 0 if there's no data, retval == 1 for EINTR if(FD_ISSET(comfd, &rfds)){ if((l = read(comfd, ptr, length)) < 1){ - return 0; + //return 0; + ERR("USB disconnected!"); } ptr += l; L += l; length -= l; @@ -359,8 +361,7 @@ int write_tty(char *buff, size_t length){ ssize_t L = write(comfd, buff, length); if((size_t)L != length){ /// "Ошибка записи!" - WARN("Write error"); - return 1; + ERR("Write error"); } return 0; } @@ -432,3 +433,149 @@ int putlog(const char *fmt, ...){ fflush(Flog); return i; } + + + +/* + * Copyright (c) 1988, 1993, 1994, 2017 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * 2017-10-14 Niklas Hamb?chen + * - Extracted signal names mapping from kill.c + * + * Copyright (C) 2014 Sami Kerola + * Copyright (C) 2014 Karel Zak + * Copyright (C) 2017 Niklas Hamb?chen + */ + +// https://github.com/karelzak/util-linux/blob/master/lib/signames.c +static const struct ul_signal_name { + const char *name; + int val; +} ul_signames[] = { + /* POSIX signals */ + { "HUP", SIGHUP }, /* 1 */ + { "INT", SIGINT }, /* 2 */ + { "QUIT", SIGQUIT }, /* 3 */ + { "ILL", SIGILL }, /* 4 */ +#ifdef SIGTRAP + { "TRAP", SIGTRAP }, /* 5 */ +#endif + { "ABRT", SIGABRT }, /* 6 */ +#ifdef SIGIOT + { "IOT", SIGIOT }, /* 6, same as SIGABRT */ +#endif +#ifdef SIGEMT + { "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */ +#endif +#ifdef SIGBUS + { "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */ +#endif + { "FPE", SIGFPE }, /* 8 */ + { "KILL", SIGKILL }, /* 9 */ + { "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */ + { "SEGV", SIGSEGV }, /* 11 */ + { "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */ + { "PIPE", SIGPIPE }, /* 13 */ + { "ALRM", SIGALRM }, /* 14 */ + { "TERM", SIGTERM }, /* 15 */ +#ifdef SIGSTKFLT + { "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */ +#endif + { "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */ +#ifdef SIGCLD + { "CLD", SIGCLD }, /* same as SIGCHLD (mips) */ +#endif + { "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */ + { "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */ + { "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */ + { "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */ + { "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */ +#ifdef SIGURG + { "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */ +#endif +#ifdef SIGXCPU + { "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */ +#endif +#ifdef SIGXFSZ + { "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */ +#endif +#ifdef SIGVTALRM + { "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */ +#endif +#ifdef SIGPROF + { "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */ +#endif +#ifdef SIGWINCH + { "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */ +#endif +#ifdef SIGIO + { "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */ +#endif +#ifdef SIGPOLL + { "POLL", SIGPOLL }, /* same as SIGIO */ +#endif +#ifdef SIGINFO + { "INFO", SIGINFO }, /* 29 (alpha) */ +#endif +#ifdef SIGLOST + { "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */ +#endif +#ifdef SIGPWR + { "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */ +#endif +#ifdef SIGUNUSED + { "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */ +#endif +#ifdef SIGSYS + { "SYS", SIGSYS }, /* 31 (mips,alpha,sparc*) */ +#endif +}; + +const char *signum_to_signame(int signum){ + size_t n; + static char buf[32]; + if(signum < 1) return NULL; +#if defined SIGRTMIN && defined SIGRTMAX + if(signum >= SIGRTMIN && signum <= SIGRTMAX){ + snprintf(buf, 32, "SIGRT%d", signum - SIGRTMIN); + return buf; + } +#endif + for (n = 0; n < ARRAY_SIZE(ul_signames); n++) { + if(ul_signames[n].val == signum){ + snprintf(buf, 32, "SIG%s", ul_signames[n].name); + return buf; + } + } + return NULL; +} diff --git a/src/netdaemon/usefull_macros.h b/src/netdaemon/usefull_macros.h index 00b6140..fe0c7fc 100644 --- a/src/netdaemon/usefull_macros.h +++ b/src/netdaemon/usefull_macros.h @@ -76,20 +76,19 @@ */ extern int globErr; extern void signals(int sig); -#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) -#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) -#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) -#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) +#define ERR(...) do{globErr=errno; putlog(__VA_ARGS__); _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; putlog(__VA_ARGS__); _WARN(__VA_ARGS__); signals(9);}while(0) +#define WARN(...) do{globErr=errno; putlog(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; putlog(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0) /* * print function name, debug messages * debug mode, -DEBUG */ #ifdef EBUG - #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) - #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n");} while(0) + #define FNAME() printf("\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{printf("%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + printf(__VA_ARGS__); printf("\n");} while(0) #else #define FNAME() do{}while(0) #define DBG(...) do{}while(0) @@ -137,4 +136,8 @@ int str2double(double *num, const char *str); void openlogfile(char *name); int putlog(const char *fmt, ...); + + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +const char *signum_to_signame(int signum); #endif // __USEFULL_MACROS_H__