Seems like it works!

This commit is contained in:
eddyem 2019-11-21 20:07:35 +03:00
parent fef588a7d1
commit 352e790706
14 changed files with 266 additions and 152 deletions

View File

@ -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")}, {"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)")}, {"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 ")")}, {"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 end_option
}; };

View File

@ -40,6 +40,7 @@ typedef struct{
int testadjfile; // test format of file with adjustments int testadjfile; // test format of file with adjustments
char *adjfilename; // name of adjustements file char *adjfilename; // name of adjustements file
char *pidfilename; // name of PID file char *pidfilename; // name of PID file
int dumpoff; // dump sensors data & turn all OFF until next request
} glob_pars; } glob_pars;

View File

@ -1,72 +0,0 @@
/*
* geany_encoding=koi8-r
* datapoints.xy - coordinates of sensors
*
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* 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}},
};

View File

@ -21,9 +21,10 @@
* *
*/ */
#include <stdio.h> // file operations #include <stdio.h> // file operations
#include <time.h>
#include <unistd.h> // access() to check file exists #include <unistd.h> // access() to check file exists
#include <linux/limits.h> // PATH_MAX #include <linux/limits.h> // PATH_MAX
#include "usefull_macros.h" // putlog #include "usefull_macros.h"
#include "cmdlnopts.h" // glob_pars #include "cmdlnopts.h" // glob_pars
extern glob_pars *G; extern glob_pars *G;
@ -32,6 +33,7 @@ static char fullpath[PATH_MAX];
// create full name from path and file // create full name from path and file
char *mkname(char *path, char *fname){ char *mkname(char *path, char *fname){
if(!path) return fname;
if(path[strlen(path)-1] == '/') snprintf(fullpath, PATH_MAX, "%s%s", path, fname); if(path[strlen(path)-1] == '/') snprintf(fullpath, PATH_MAX, "%s%s", path, fname);
else snprintf(fullpath, PATH_MAX, "%s/%s", path, fname); else snprintf(fullpath, PATH_MAX, "%s/%s", path, fname);
DBG("fullpath: %s", fullpath); 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){ static int formfile(char *fname, double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], int Z){
FILE *F = fopen(fname, "w"); FILE *F = fopen(fname, "w");
if(!F) return 0; if(!F) return 0;
int nonzero_values = 0;
for(int i = 1; i <= NCTRLR_MAX; ++i){ for(int i = 1; i <= NCTRLR_MAX; ++i){
for(int N = 0; N <= NCHANNEL_MAX; ++ N) for(int p = 0; p < 2; ++p){ for(int N = 0; N <= NCHANNEL_MAX; ++ N) for(int p = 0; p < 2; ++p){
double T = data[p][N][i]; 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(!sdata) continue;
if(Z != sdata->Z) continue; if(Z != sdata->Z) continue;
fprintf(F, "%d\t%d\t%.2f\n", sdata->X, sdata->Y, T - sdata->dt - sdata->Tadj); fprintf(F, "%d\t%d\t%.2f\n", sdata->X, sdata->Y, T - sdata->dt - sdata->Tadj);
++nonzero_values;
} }
} }
} }
fclose(F); fclose(F);
if(!nonzero_values) return 0;
DBG("File %s ready", fname); DBG("File %s ready", fname);
return 1; 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){ static void gnuplot(char *path, char *fname){
char *ctmp = mkname(path, "plot"); char *ctmp = mkname(path, "plot");
char buf[PATH_MAX*2]; char buf[PATH_MAX*2], *ptr = buf;
size_t L = PATH_MAX*2; size_t L = PATH_MAX*2;
if(access(ctmp, F_OK)){ if(access(ctmp, F_OK)){
WARNX(_("Don't find %s to plot graphics"), ctmp); WARNX(_("Don't find %s to plot graphics"), ctmp);
putlog("Don't find %s to plot graphics", ctmp);
return; return;
} }
ssize_t l = snprintf(buf, L, "%s ", ctmp); ssize_t l = snprintf(ptr, L, "%s ", ctmp);
if(l < 1) return; if(l < 1) return;
L -= l; ptr += l;
ctmp = mkname(path, fname); 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); DBG("Run %s", buf);
if(system(buf)){ if(system(buf)){
WARNX(_("Can't run `%s`"), 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){ 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"); char *ctmp = mkname(savepath, "T0");
if(formfile(ctmp, data, 0)) if(G->makegraphs) gnuplot(savepath, "T0"); if(formfile(ctmp, data, 0)) if(G->makegraphs) gnuplot(savepath, "T0");
ctmp = mkname(savepath, "T1"); ctmp = mkname(savepath, "T1");
if(formfile(ctmp, data, 1)) if(G->makegraphs) gnuplot(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");
} }

View File

@ -24,6 +24,7 @@
#include "checkfile.h" #include "checkfile.h"
#include "cmdlnopts.h" #include "cmdlnopts.h"
#include "socket.h" #include "socket.h"
#include "term.h"
#include "usefull_macros.h" #include "usefull_macros.h"
glob_pars *G; // non-static: some another files should know about it! 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){ void signals(int signo){
restore_console(); restore_console();
restore_tty(); 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); 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 // SIGUSR1 handler - re-read Tadj file
void refreshAdj(_U_ int signo){ static void refreshAdj(_U_ int signo){
DBG("refresh adj"); DBG("refresh adj");
if(childpid){ // I am a master if(childpid){ // I am a master
putlog("Force child %d to re-read adj-file", childpid); 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){ int main(int argc, char **argv){
initial_setup(); initial_setup();
G = parse_args(argc, argv); G = parse_args(argc, argv);
@ -57,9 +77,13 @@ int main(int argc, char **argv){
if(G->makegraphs && !G->savepath){ if(G->makegraphs && !G->savepath){
ERRX(_("Point the path to graphical files")); 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); 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(G->testadjfile){
if(raf == 0){ if(raf == 0){
green("Format of file %s is right\n", G->adjfilename); green("Format of file %s is right\n", G->adjfilename);
@ -71,12 +95,16 @@ int main(int argc, char **argv){
return 1; return 1;
} }
if(runningproc) ERRX("Found running process, pid=%d.", runningproc); 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(SIGTERM, signals); // kill (-15) - quit
signal(SIGHUP, SIG_IGN); // hup - ignore signal(SIGHUP, SIG_IGN); // hup - ignore
signal(SIGCHLD, SIG_DFL); // chld - default
signal(SIGINT, signals); // ctrl+C - quit signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
signal(SIGUSR1, refreshAdj); // refresh adjustements signal(SIGUSR1, refreshAdj); // refresh adjustements
signal(SIGUSR2, logT); // print all current temperatures into logfile and turn off sensors
#ifndef EBUG #ifndef EBUG
if(!G->terminal){ if(!G->terminal){
if(daemon(1, 0)){ if(daemon(1, 0)){
@ -87,10 +115,9 @@ int main(int argc, char **argv){
if(childpid){ if(childpid){
putlog("create child with PID %d\n", childpid); putlog("create child with PID %d\n", childpid);
DBG("Created child with PID %d\n", childpid); DBG("Created child with PID %d\n", childpid);
wait(NULL); while(childpid != waitpid(childpid, NULL, 0));
putlog("child %d died\n", childpid);
WARNX("Child %d died\n", childpid); WARNX("Child %d died\n", childpid);
sleep(1); sleep(10);
}else{ }else{
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
break; // go out to normal functional break; // go out to normal functional

View File

@ -32,7 +32,7 @@ set xrange [-30:30]
set yrange [-30:30] set yrange [-30:30]
set xlabel "X, dm" set xlabel "X, dm"
set ylabel "Y, dm" set ylabel "Y, dm"
set title "Mirror temperature" set title "Mirror temperature $2"
set pm3d map set pm3d map
unset key unset key
circle(x,y,z) = x**2+y**2 > 900 ? NaN : z circle(x,y,z) = x**2+y**2 > 900 ? NaN : z

View File

@ -202,14 +202,15 @@ const sensor_data *get_sensor_location(int Nct, int Nch, int Ns){
return NULL; return NULL;
} }
int idx = 2*(NCHANNEL_MAX+1)*(Nct - 1) + 2*Nch + Ns; 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; 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 s;
} }
// return next non-space character in line until first '\n' or NULL if met '#' or '\n' // return next non-space character in line until first '\n' or NULL if met '#' or '\n'
static char *omitspaces(char *str){ static char *omitspaces(char *str){
if(!str) return NULL;
char ch; char ch;
do{ do{
ch = *str; ch = *str;
@ -243,7 +244,6 @@ int read_adj_file(char *fname){
mmapbuf *buf = My_mmap(fname); mmapbuf *buf = My_mmap(fname);
if(!buf) return 1; if(!buf) return 1;
char *adjf = buf->data, *eof = adjf + buf->len; char *adjf = buf->data, *eof = adjf + buf->len;
DBG("buf: %s", adjf);
int strnum = 1; // start string number from 1 int strnum = 1; // start string number from 1
while(adjf < eof){ while(adjf < eof){
char *eol = strchr(adjf, '\n'); char *eol = strchr(adjf, '\n');
@ -251,24 +251,20 @@ int read_adj_file(char *fname){
if(!nextchar){ if(!nextchar){
goto cont; goto cont;
} }
DBG("First char: %c", *nextchar);
char *endptr = NULL; char *endptr = NULL;
long num = strtol(nextchar, &endptr, 10); long num = strtol(nextchar, &endptr, 10);
if(endptr == nextchar || !endptr){ if(endptr == nextchar || !endptr){
WARNX("Wrong integer number!"); WARNX("Wrong integer number!");
goto reperr; goto reperr;
} }
DBG("first num: %ld", num);
int Nctrl = num / 100; int Nctrl = num / 100;
int Nch = (num - Nctrl*100) / 10; int Nch = (num - Nctrl*100) / 10;
int Nsen = num%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)){ if(num < 0 || (Nsen != 0 && Nsen != 1) || (Nch < 0 || Nch > NCHANNEL_MAX) || (Nctrl < 1 || Nctrl > NCTRLR_MAX)){
WARNX("Wrong sensor number: %ld", num); WARNX("Wrong sensor number: %ld", num);
goto reperr; goto reperr;
} }
int idx = 2*(NCHANNEL_MAX+1)*(Nctrl - 1) + 2*Nch + Nsen; int idx = 2*(NCHANNEL_MAX+1)*(Nctrl - 1) + 2*Nch + Nsen;
DBG("index: %d", idx);
if(idx < 0 || idx > NSENSORS-1){ if(idx < 0 || idx > NSENSORS-1){
WARNX("Sensor index (%d) over range 0..%d", 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!"); WARNX("Wrong double number!");
goto reperr; goto reperr;
} }
DBG("double num: %g", t);
Tadj[idx] = t; Tadj[idx] = t;
if(omitspaces(endptr)){ if(omitspaces(endptr)){
WARNX("Wrong file format: each string should include two numbers (and maybe comment after #)"); WARNX("Wrong file format: each string should include two numbers (and maybe comment after #)");
@ -294,10 +289,12 @@ cont:
++strnum; ++strnum;
} }
My_munmap(buf); My_munmap(buf);
printf("Non-zero components:\n");
for(int i = 0; i < NSENSORS; ++i){ for(int i = 0; i < NSENSORS; ++i){
if(fabs(Tadj[i]) > DBL_EPSILON){ 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]; sensors[i].Tadj = Tadj[i];
} }
return 0; return 0;

View File

@ -46,6 +46,16 @@ static double meanT;
extern glob_pars *G; 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 ****************/ /**************** COMMON FUNCTIONS ****************/
/** /**
* wait for answer from socket * 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 // search a first word after needle without spaces
static char* stringscan(char *str, char *needle){ static char* stringscan(char *str, char *needle){
if(!str || !needle) return NULL;
char *a, *e; char *a, *e;
char *end = str + strlen(str); char *end = str + strlen(str);
a = strstr(str, needle); a = strstr(str, needle);
@ -134,8 +145,8 @@ static char* stringscan(char *str, char *needle){
} }
static void *handle_socket(void *asock){ static void *handle_socket(void *asock){
//putlog("handle_socket(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid));
FNAME(); FNAME();
if(!asock) return NULL;
int sock = *((int*)asock); int sock = *((int*)asock);
int webquery = 0; // whether query is web or regular int webquery = 0; // whether query is web or regular
char buff[BUFLEN]; char buff[BUFLEN];
@ -147,13 +158,10 @@ static void *handle_socket(void *asock){
continue; continue;
} }
if(!(rd = read(sock, buff, BUFLEN-1))){ if(!(rd = read(sock, buff, BUFLEN-1))){
//putlog("socket closed. Exit");
break; break;
} }
//putlog("client send %zd bytes", rd);
DBG("Got %zd bytes", rd); DBG("Got %zd bytes", rd);
if(rd < 0){ // error if(rd < 0){ // error
//putlog("some error occured");
DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); DBG("Nothing to read from fd %d (ret: %zd)", sock, rd);
break; break;
} }
@ -181,24 +189,21 @@ static void *handle_socket(void *asock){
char tbuf[10]; char tbuf[10];
ssize_t L = snprintf(tbuf, 10, "%.2f", meanT); ssize_t L = snprintf(tbuf, 10, "%.2f", meanT);
if(L != write(sock, tbuf, L)) WARN("write()"); if(L != write(sock, tbuf, L)) WARN("write()");
//DBG("Ask Tmean = %g", meanT);
} // here can be more parsers } // here can be more parsers
break; break;
} }
close(sock); close(sock);
//DBG("closed");
//putlog("socket closed, exit");
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
} }
// main socket server // main socket server
static void *server(void *asock){ 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); int sock = *((int*)asock);
if(listen(sock, BACKLOG) == -1){ if(listen(sock, BACKLOG) == -1){
putlog("listen() failed"); WARN("listen()");
WARN("listen");
return NULL; return NULL;
} }
while(1){ while(1){
@ -208,7 +213,6 @@ static void *server(void *asock){
if(!waittoread(sock)) continue; if(!waittoread(sock)) continue;
newsock = accept(sock, (struct sockaddr*)&their_addr, &size); newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
if(newsock <= 0){ if(newsock <= 0){
putlog("accept() failed");
WARN("accept()"); WARN("accept()");
continue; continue;
} }
@ -220,7 +224,6 @@ static void *server(void *asock){
red("Got connection from %s\n", str); red("Got connection from %s\n", str);
pthread_t handler_thread; pthread_t handler_thread;
if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){
putlog("server(): pthread_create() failed");
WARN("pthread_create()"); WARN("pthread_create()");
}else{ }else{
DBG("Thread created, detouch"); DBG("Thread created, detouch");
@ -323,6 +326,7 @@ static void process_T(){
} }
// make graphics // make graphics
if(G->savepath){ if(G->savepath){
DBG("GOT %dTH MEAN DATA", Nmeanmax+1);
if(++Nmeanmax == GRAPHS_AMOUNT){ if(++Nmeanmax == GRAPHS_AMOUNT){
for(i = 1; i <= NCTRLR_MAX; ++i)for(N = 0; N <= NCHANNEL_MAX; ++ N)for(p = 0; p < 2; ++p){ 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]){ if(Nmean[p][N][i]){
@ -331,7 +335,9 @@ static void process_T(){
}else Tmean[p][N][i] = -300.; // no data }else Tmean[p][N][i] = -300.; // no data
} }
plot(Tmean, G->savepath); plot(Tmean, G->savepath);
DBG("memset start");
memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1)); memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1));
DBG("memset end");
Nmeanmax = 0; Nmeanmax = 0;
} }
} }
@ -344,21 +350,27 @@ static void daemon_(int sock){
if(sock < 0) return; if(sock < 0) return;
pthread_t sock_thread; pthread_t sock_thread;
if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){
putlog("daemon_(): pthread_create() failed");
ERR("pthread_create()"); ERR("pthread_create()");
} }
double tgot = 0.; double tgot = 0., tlastoff = dtime();
do{ do{
if(pthread_kill(sock_thread, 0) == ESRCH){ // died if(pthread_kill(sock_thread, 0) == ESRCH){ // died
WARNX("Sockets thread died"); WARNX("Sockets thread died");
putlog("Sockets thread died");
pthread_join(sock_thread, NULL); pthread_join(sock_thread, NULL);
if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){
putlog("daemon_(): new pthread_create() failed");
ERR("pthread_create()"); ERR("pthread_create()");
} }
} }
usleep(1000); // sleep a little or thread's won't be able to lock mutex 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; if(dtime() - tgot < T_INTERVAL) continue;
// get data // get data
int i; int i;
@ -407,6 +419,7 @@ static void daemon_(int sock){
* Run daemon service * Run daemon service
*/ */
void daemonize(char *port){ void daemonize(char *port){
if(!port) return;
FNAME(); FNAME();
int sock = -1; int sock = -1;
struct addrinfo hints, *res, *p; struct addrinfo hints, *res, *p;
@ -439,14 +452,13 @@ void daemonize(char *port){
break; // if we get here, we have a successfull connection break; // if we get here, we have a successfull connection
} }
if(p == NULL){ if(p == NULL){
putlog("failed to bind socket, exit");
// looped off the end of the list with no successful bind // looped off the end of the list with no successful bind
ERRX("failed to bind socket"); ERRX("failed to bind socket");
} }
freeaddrinfo(res); freeaddrinfo(res);
daemon_(sock); daemon_(sock);
close(sock); close(sock);
putlog("socket closed, exit"); putlog("daemonize(): UNREACHABLE CODE REACHED!");
signals(0); signals(0);
} }

View File

@ -28,5 +28,7 @@
#define SOCKET_TIMEOUT (5.0) #define SOCKET_TIMEOUT (5.0)
void daemonize(char *port); void daemonize(char *port);
const char *gotstr(int N);
void TurnOFF();
#endif // __SOCKET_H__ #endif // __SOCKET_H__

View File

@ -1,6 +1 @@
#No dT (Treal = T - dT) #No dT (Treal = T - dT)
100 -0.02
101 3.
# some more comments
560 -0.06 # another comment
571 -0.01 # test

View File

@ -209,7 +209,13 @@ int poll_sensors(int N){
return 1; 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 * check whether connected device is main Thermal controller

View File

@ -24,21 +24,22 @@
#include "sens_place.h" // NCTRLR #include "sens_place.h" // NCTRLR
#define FRAME_MAX_LENGTH (300)
#define MAX_MEMORY_DUMP_SIZE (0x800 * 4)
// Terminal timeout (seconds) // Terminal timeout (seconds)
#define WAIT_TMOUT (0.5) #define WAIT_TMOUT (0.5)
// Main controller polling timeout - 1 second // Main controller polling timeout - 1 second
#define POLLING_TMOUT (1.0) #define POLLING_TMOUT (1.0)
// Thermal polling timeout: 5 seconds // Thermal polling timeout: 5 seconds
#define T_POLLING_TMOUT (5.0) #define T_POLLING_TMOUT (5.0)
// T measurement time interval - 1 minute // T measurement time interval - 30 seconds
#define T_INTERVAL (60.0) #define T_INTERVAL (30.0)
// Interval of turning sensors off - 3 days
#define T_OFF_INTERVAL (259200.)
// amount of measurement to plot mean graphs // amount of measurement to plot mean graphs
#define GRAPHS_AMOUNT (15) #define GRAPHS_AMOUNT (15)
// Protocol // Protocol
#define CMD_SENSORS_OFF 'F' #define CMD_SENSORS_OFF 'F'
#define CMD_SENSORS_OFF_LOCAL 'f'
#define CMD_VOLTAGE 'K' #define CMD_VOLTAGE 'K'
#define CMD_PING 'P' #define CMD_PING 'P'
#define CMD_MEASURE_T 'T' #define CMD_MEASURE_T 'T'
@ -59,5 +60,6 @@ void run_terminal();
void try_connect(char *device); void try_connect(char *device);
int poll_sensors(int N); int poll_sensors(int N);
int check_sensors(); int check_sensors();
void turn_all_off();
#endif // __TERM_H__ #endif // __TERM_H__

View File

@ -22,6 +22,7 @@
#include "usefull_macros.h" #include "usefull_macros.h"
#include <time.h> #include <time.h>
#include <linux/limits.h> // PATH_MAX #include <linux/limits.h> // PATH_MAX
#include <signal.h>
/** /**
* function for different purposes that need to know time intervals * function for different purposes that need to know time intervals
@ -286,7 +287,7 @@ void restore_tty(){
} }
#ifndef BAUD_RATE #ifndef BAUD_RATE
#define BAUD_RATE B4800 #define BAUD_RATE B9600
#endif #endif
// init: // init:
void tty_init(char *comdev){ void tty_init(char *comdev){
@ -343,10 +344,11 @@ size_t read_tty(char *buff, size_t length){
// wait for 100ms // wait for 100ms
tv.tv_sec = 0; tv.tv_usec = 100000; tv.tv_sec = 0; tv.tv_usec = 100000;
retval = select(comfd + 1, &rfds, NULL, NULL, &tv); 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(FD_ISSET(comfd, &rfds)){
if((l = read(comfd, ptr, length)) < 1){ if((l = read(comfd, ptr, length)) < 1){
return 0; //return 0;
ERR("USB disconnected!");
} }
ptr += l; L += l; ptr += l; L += l;
length -= l; length -= l;
@ -359,8 +361,7 @@ int write_tty(char *buff, size_t length){
ssize_t L = write(comfd, buff, length); ssize_t L = write(comfd, buff, length);
if((size_t)L != length){ if((size_t)L != length){
/// "ïÛÉÂËÁ ÚÁÐÉÓÉ!" /// "ïÛÉÂËÁ ÚÁÐÉÓÉ!"
WARN("Write error"); ERR("Write error");
return 1;
} }
return 0; return 0;
} }
@ -432,3 +433,149 @@ int putlog(const char *fmt, ...){
fflush(Flog); fflush(Flog);
return i; 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 <mail@nh2.me>
* - Extracted signal names mapping from kill.c
*
* Copyright (C) 2014 Sami Kerola <kerolasa@iki.fi>
* Copyright (C) 2014 Karel Zak <kzak@redhat.com>
* Copyright (C) 2017 Niklas Hamb?chen <mail@nh2.me>
*/
// 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;
}

View File

@ -76,20 +76,19 @@
*/ */
extern int globErr; extern int globErr;
extern void signals(int sig); extern void signals(int sig);
#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) #define ERR(...) do{globErr=errno; putlog(__VA_ARGS__); _WARN(__VA_ARGS__); signals(9);}while(0)
#define ERRX(...) do{globErr=0; _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; _WARN(__VA_ARGS__);}while(0) #define WARN(...) do{globErr=errno; putlog(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0)
#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) #define WARNX(...) do{globErr=0; putlog(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0)
/* /*
* print function name, debug messages * print function name, debug messages
* debug mode, -DEBUG * debug mode, -DEBUG
*/ */
#ifdef EBUG #ifdef EBUG
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) #define FNAME() printf("\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
#define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ #define DBG(...) do{printf("%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \ printf(__VA_ARGS__); printf("\n");} while(0)
fprintf(stderr, "\n");} while(0)
#else #else
#define FNAME() do{}while(0) #define FNAME() do{}while(0)
#define DBG(...) do{}while(0) #define DBG(...) do{}while(0)
@ -137,4 +136,8 @@ int str2double(double *num, const char *str);
void openlogfile(char *name); void openlogfile(char *name);
int putlog(const char *fmt, ...); 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__ #endif // __USEFULL_MACROS_H__