start to fix errors. 1. Tadj added

This commit is contained in:
eddyem 2019-11-20 17:43:51 +03:00
parent f34c50bbaf
commit fef588a7d1
13 changed files with 621 additions and 936 deletions

File diff suppressed because it is too large Load Diff

127
src/netdaemon/checkfile.c Normal file
View File

@ -0,0 +1,127 @@
/*
* daemon.c - functions for running in background like a daemon
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* 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.
*/
#include <dirent.h> // opendir
#include "checkfile.h"
#include "usefull_macros.h"
/**
* @brief readPSname - read process name from /proc/PID/cmdline
* @param pid - PID of interesting process
* @return filename or NULL if not found
* don't use this function twice for different names without copying
* its returning by strdup, because `name` contains in static array
*/
char *readPSname(pid_t pid){
static char name[PATH_MAX];
char *pp = name, byte, path[PATH_MAX];
FILE *file;
int cntr = 0;
size_t sz;
snprintf(path, PATH_MAX, PROC_BASE "/%d/cmdline", pid);
file = fopen(path, "r");
if(!file) return NULL; // there's no such file
do{ // read basename
sz = fread(&byte, 1, 1, file);
if(sz != 1) break;
if(byte != '/') *pp++ = byte;
else{
pp = name;
cntr = 0;
}
}while(byte && cntr++ < PATH_MAX-1);
name[cntr] = 0;
fclose(file);
return name;
}
static char *pidfilename_ = NULL; // store the name of pidfile here
/**
* check wether there is a same running process
* exit if there is a running process or error
* Checking have 3 steps:
* 1) lock executable file
* 2) check pidfile (if you run a copy?)
* 3) check /proc for executables with the same name (no/wrong pidfile)
* @param pidfilename - name of pidfile or NULL if none
* @return 0 if all OK or PID of first running process found
*/
pid_t check4running(char *pidfilename){
DIR *dir;
FILE *pidfile;
struct dirent *de;
struct stat s_buf;
pid_t pid = 0, self;
char *name, *myname;
self = getpid(); // get self PID
if(!(dir = opendir(PROC_BASE))){ // open /proc directory
ERR(PROC_BASE);
}
if(!(name = readPSname(self))){ // error reading self name
ERR("Can't read self name");
}
myname = strdup(name);
if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists
pidfile = fopen(pidfilename, "r");
if(pidfile){
if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0){
fclose(pidfile);
goto procfound;
}
}
fclose(pidfile);
}
}
// There is no pidfile or it consists a wrong record
while((de = readdir(dir))){ // scan /proc
if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self
continue;
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0)
goto procfound;
}
pid = 0; // OK, not found -> create pid-file if need
if(pidfilename){
pidfile = fopen(pidfilename, "w");
if(!pidfile){
WARN("Can't open PID file");
}else{
fprintf(pidfile, "%d\n", self); // write self PID to pidfile
fclose(pidfile);
if(pidfilename_) FREE(pidfilename_);
pidfilename_ = strdup(pidfilename);
}
}
procfound:
closedir(dir);
free(myname);
return pid;
}
/**
* @brief unlink_pidfile - remove pidfile @ exit
*/
void unlink_pidfile(){
if(!pidfilename_) return;
unlink(pidfilename_);
FREE(pidfilename_);
}

39
src/netdaemon/checkfile.h Normal file
View File

@ -0,0 +1,39 @@
/*
* This file is part of the Zphocus project.
* Copyright 2019 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef CHECKFILE_H__
#define CHECKFILE_H__
#include <unistd.h> // getpid, unlink
#ifndef PROC_BASE
#define PROC_BASE "/proc"
#endif
#ifndef WEAK
#define WEAK __attribute__ ((weak))
#endif
// check that our process is exclusive
pid_t check4running(char *pidfilename);
// read name of process by its PID
char *readPSname(pid_t pid);
void unlink_pidfile();
#endif // CHECKFILE_H__

View File

@ -35,6 +35,7 @@ static glob_pars G;
// default values for Gdefault & help // default values for Gdefault & help
#define DEFAULT_COMDEV "/dev/ttyUSB0" #define DEFAULT_COMDEV "/dev/ttyUSB0"
#define DEFAULT_PORT "4444" #define DEFAULT_PORT "4444"
#define DEFAULT_PIDFILE "/tmp/TSYS01daemon.pid"
// DEFAULTS // DEFAULTS
// default global parameters // default global parameters
@ -45,7 +46,9 @@ glob_pars const Gdefault = {
.savepath = NULL, .savepath = NULL,
.makegraphs = 0, .makegraphs = 0,
.rest_pars = NULL, .rest_pars = NULL,
.rest_pars_num = 0 .rest_pars_num = 0,
.adjfilename = "tempadj.txt",
.pidfilename = DEFAULT_PIDFILE
}; };
/* /*
@ -60,6 +63,9 @@ myoption cmdlnopts[] = {
{"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")}, {"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")},
{"savepath",NEED_ARG, NULL, 's', arg_string, APTR(&G.savepath), _("path where files would be saved (if none - don't save)")}, {"savepath",NEED_ARG, NULL, 's', arg_string, APTR(&G.savepath), _("path where files would be saved (if none - don't save)")},
{"graphplot",NO_ARGS, NULL, 'g', arg_int, APTR(&G.makegraphs),_("make graphics with gnuplot")}, {"graphplot",NO_ARGS, NULL, 'g', arg_int, APTR(&G.makegraphs),_("make graphics with gnuplot")},
{"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 ")")},
end_option end_option
}; };

View File

@ -37,6 +37,9 @@ typedef struct{
int makegraphs; // ==1 to make graphics with gnuplot int makegraphs; // ==1 to make graphics with gnuplot
int rest_pars_num; // number of rest parameters int rest_pars_num; // number of rest parameters
char** rest_pars; // the rest parameters: array of char* (path to logfile and thrash) char** rest_pars; // the rest parameters: array of char* (path to logfile and thrash)
int testadjfile; // test format of file with adjustments
char *adjfilename; // name of adjustements file
char *pidfilename; // name of PID file
} glob_pars; } glob_pars;

View File

@ -55,7 +55,7 @@ static int formfile(char *fname, double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], i
const sensor_data *sdata = get_sensor_location(i, N, p); const sensor_data *sdata = get_sensor_location(i, N, p);
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); fprintf(F, "%d\t%d\t%.2f\n", sdata->X, sdata->Y, T - sdata->dt - sdata->Tadj);
} }
} }
} }

View File

@ -18,15 +18,18 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. * MA 02110-1301, USA.
*/ */
#include "usefull_macros.h"
#include <signal.h> #include <signal.h>
#include <sys/wait.h> // wait #include <sys/wait.h> // wait
#include <sys/prctl.h> //prctl #include <sys/prctl.h> //prctl
#include "checkfile.h"
#include "cmdlnopts.h" #include "cmdlnopts.h"
#include "socket.h" #include "socket.h"
#include "usefull_macros.h"
glob_pars *G; glob_pars *G; // non-static: some another files should know about it!
static pid_t childpid = 0; // PID of child - to kill it if need
// default signals handler
void signals(int signo){ void signals(int signo){
restore_console(); restore_console();
restore_tty(); restore_tty();
@ -34,25 +37,53 @@ void signals(int signo){
exit(signo); exit(signo);
} }
// SIGUSR1 handler - re-read Tadj file
void refreshAdj(_U_ int signo){
DBG("refresh adj");
if(childpid){ // I am a master
putlog("Force child %d to re-read adj-file", childpid);
kill(childpid, SIGUSR1);
}else{ // I am a child
putlog("Re-read adj-file");
read_adj_file(G->adjfilename);
}
}
int main(int argc, char **argv){ int main(int argc, char **argv){
initial_setup(); initial_setup();
signal(SIGTERM, signals); // kill (-15) - quit
signal(SIGHUP, SIG_IGN); // hup - ignore
signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
G = parse_args(argc, argv); G = parse_args(argc, argv);
if(G->rest_pars_num) if(G->rest_pars_num)
openlogfile(G->rest_pars[0]); openlogfile(G->rest_pars[0]);
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);
if(G->testadjfile){
if(raf == 0){
green("Format of file %s is right\n", G->adjfilename);
if(runningproc){ // fore running process to re-read it
kill(runningproc, SIGUSR1);
}
return 0;
}
return 1;
}
if(runningproc) ERRX("Found running process, pid=%d.", runningproc);
signal(SIGTERM, signals); // kill (-15) - quit
signal(SIGHUP, SIG_IGN); // hup - ignore
signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
signal(SIGUSR1, refreshAdj); // refresh adjustements
#ifndef EBUG #ifndef EBUG
if(!G->terminal){
if(daemon(1, 0)){ if(daemon(1, 0)){
ERR("daemon()"); ERR("daemon()");
} }
while(1){ // guard for dead processes while(1){ // guard for dead processes
pid_t childpid = fork(); childpid = fork();
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);
@ -65,6 +96,7 @@ int main(int argc, char **argv){
break; // go out to normal functional break; // go out to normal functional
} }
} }
}
#endif #endif
DBG("dev: %s", G->device); DBG("dev: %s", G->device);
try_connect(G->device); try_connect(G->device);

View File

@ -19,6 +19,7 @@
#include "sens_place.h" #include "sens_place.h"
#include "stdbool.h" #include "stdbool.h"
#include "usefull_macros.h" #include "usefull_macros.h"
#include "math.h" // fabs
/** /**
Sensor place Dt X Y Z Sensor place Dt X Y Z
@ -104,97 +105,96 @@
571 18 0.02 13 3 0 571 18 0.02 13 3 0
*/ */
static const sensor_data sensors[] = { static sensor_data sensors[NSENSORS] = {
// {Dt,X,Y,Z}, // {Dt,X,Y,Z},
{-0.07, 19, 7, 0}, // 0 {-0.07, 19, 7, 0, 0}, // 0
{0.03, 20, 0, 0}, // 1 {0.03, 20, 0, 0, 0}, // 1
{0.03, 19, -7, 0}, // 2 {0.03, 19, -7, 0, 0}, // 2
{-0.05, 17, -10, 1}, // 3 {-0.05, 17, -10, 1, 0}, // 3
{0.02, 17, -22, 0}, // 4 {0.02, 17, -22, 0, 0}, // 4
{-0.03, 15, -13, 0}, // 5 {-0.03, 15, -13, 0, 0}, // 5
{0.02, 22, -17, 0}, // 6 {0.02, 22, -17, 0, 0}, // 6
{-0.09, 24, -14, 1}, // 7 {-0.09, 24, -14, 1, 0}, // 7
{0.03, 25, -10, 0}, // 8 {0.03, 25, -10, 0, 0}, // 8
{0.02, 27, -4, 0}, // 9 {0.02, 27, -4, 0, 0}, // 9
{-0.01, 27, 4, 0}, // 10 {-0.01, 27, 4, 0, 0}, // 10
{-0.09, 25, 10, 0}, // 11 {-0.09, 25, 10, 0, 0}, // 11
{0.07, 22, 17, 0}, // 12 {0.07, 22, 17, 0, 0}, // 12
{0, 24, 14, 1}, // 13 {0, 24, 14, 1, 0}, // 13
{0.02, 10, 25, 0}, // 14 {0.02, 10, 25, 0, 0}, // 14
{0.08, 17, 22, 0}, // 15 {0.08, 17, 22, 0, 0}, // 15
{-0.01, 4, 27, 0}, // 16 {-0.01, 4, 27, 0, 0}, // 16
{-0.03, 0, 27, 1}, // 17 {-0.03, 0, 27, 1, 0}, // 17
{0.04, -4, 27, 0}, // 18 {0.04, -4, 27, 0, 0}, // 18
{-0.01, -10, 25, 0}, // 19 {-0.01, -10, 25, 0, 0}, // 19
{-0.02, -17, 22, 0}, // 20 {-0.02, -17, 22, 0, 0}, // 20
{-0.04, -22, 17, 0}, // 21 {-0.04, -22, 17, 0, 0}, // 21
{0.03, -25, 10, 0}, // 22 {0.03, -25, 10, 0, 0}, // 22
{-0.03, -24, 14, 1}, // 23 {-0.03, -24, 14, 1, 0}, // 23
{-0.03, -27, -4, 0}, // 24 {-0.03, -27, -4, 0, 0}, // 24
{0.03, -27, 4, 0}, // 25 {0.03, -27, 4, 0, 0}, // 25
{-0.05, -25, -10, 0}, // 26 {-0.05, -25, -10, 0, 0}, // 26
{0, -24, -14, 1}, // 27 {0, -24, -14, 1, 0}, // 27
{0.03, -22, -17, 0}, // 28 {0.03, -22, -17, 0, 0}, // 28
{-0.05, -17, -22, 0}, // 29 {-0.05, -17, -22, 0, 0}, // 29
{-0.02, -10, -25, 0}, // 30 {-0.02, -10, -25, 0, 0}, // 30
{0.04, -4, -27, 0}, // 31 {0.04, -4, -27, 0, 0}, // 31
{0.12, -3, -20, 0}, // 32 {0.12, -3, -20, 0, 0}, // 32
{0, -10, -17, 0}, // 33 {0, -10, -17, 0, 0}, // 33
{-0.08, -15, -13, 0}, // 34 {-0.08, -15, -13, 0, 0}, // 34
{-0.08, -17, -10, 1}, // 35 {-0.08, -17, -10, 1, 0}, // 35
{-0.1, -19, -7, 0}, // 36 {-0.1, -19, -7, 0, 0}, // 36
{-0.04, -20, 0, 0}, // 37 {-0.04, -20, 0, 0, 0}, // 37
{-0.08, -19, 7, 0}, // 38 {-0.08, -19, 7, 0, 0}, // 38
{0.03, -17, 10, 1}, // 39 {0.03, -17, 10, 1, 0}, // 39
{0.11, -15, 13, 0}, // 40 {0.11, -15, 13, 0, 0}, // 40
{0.07, -10, 17, 0}, // 41 {0.07, -10, 17, 0, 0}, // 41
{0.09, -3, 20, 0}, // 42 {0.09, -3, 20, 0, 0}, // 42
{-0.09, 0, 20, 1}, // 43 {-0.09, 0, 20, 1, 0}, // 43
{-0.1, 3, 20, 0}, // 44 {-0.1, 3, 20, 0, 0}, // 44
{0.04, 10, 17, 0}, // 45 {0.04, 10, 17, 0, 0}, // 45
{0.05, 15, 13, 0}, // 46 {0.05, 15, 13, 0, 0}, // 46
{-0.04, 17, 10, 1}, // 47 {-0.04, 17, 10, 1, 0}, // 47
{0.01, 9, 9, 0}, // 48 {0.01, 9, 9, 0, 0}, // 48
{-0.04, 11, 7, 1}, // 49 {-0.04, 11, 7, 1, 0}, // 49
{0.01, 3, 13, 0}, // 50 {0.01, 3, 13, 0, 0}, // 50
{-0.04, 0, 13, 1}, // 51 {-0.04, 0, 13, 1, 0}, // 51
{0.14, -9, 9, 0}, // 52 {0.14, -9, 9, 0, 0}, // 52
{0, -3, 13, 0}, // 53 {0, -3, 13, 0, 0}, // 53
{0.07, -13, 3, 0}, // 54 {0.07, -13, 3, 0, 0}, // 54
{-0.02, -11, 7, 1}, // 55 {-0.02, -11, 7, 1, 0}, // 55
{0.04, -13, -3, 0}, // 56 {0.04, -13, -3, 0, 0}, // 56
{-0.06, -11, -7, 1}, // 57 {-0.06, -11, -7, 1, 0}, // 57
{0.01, -9, -9, 0}, // 58 {0.01, -9, -9, 0, 0}, // 58
{0.08, -3, -13, 0}, // 59 {0.08, -3, -13, 0, 0}, // 59
{-0.09, 3, -13, 0}, // 60 {-0.09, 3, -13, 0, 0}, // 60
{-0.04, 0, -13, 1}, // 61 {-0.04, 0, -13, 1, 0}, // 61
{0.06, 3, -20, 0}, // 62 {0.06, 3, -20, 0, 0}, // 62
{-0.05, 0, -20, 1}, // 63 {-0.05, 0, -20, 1, 0}, // 63
{0.05, 4, -27, 0}, // 64 {0.05, 4, -27, 0, 0}, // 64
{-0.08, 0, -27, 1}, // 65 {-0.08, 0, -27, 1, 0}, // 65
{0.1, 10, -17, 0}, // 66 {0.1, 10, -17, 0, 0}, // 66
{-0.05, 10, -25, 0}, // 67 {-0.05, 10, -25, 0, 0}, // 67
{0, 9, -9, 0}, // 68 {0, 9, -9, 0, 0}, // 68
{0.01, 11, -7, 1}, // 69 {0.01, 11, -7, 1, 0}, // 69
{0, 3, -5, 0}, // 70 {0, 3, -5, 0, 0}, // 70
{-0.02, 0, -6, 1}, // 71 {-0.02, 0, -6, 1, 0}, // 71
{0.05, -3, -5, 0}, // 72 {0.05, -3, -5, 0, 0}, // 72
{-0.03, -6, 0, 0}, // 73 {-0.03, -6, 0, 0, 0}, // 73
{0.03, -3, 5, 0}, // 74 {0.03, -3, 5, 0, 0}, // 74
{0.06, 0, 6, 1}, // 75 {0.06, 0, 6, 1, 0}, // 75
{0, 3, 5, 0}, // 76 {0, 3, 5, 0, 0}, // 76
{-0.06, 6, 0, 0}, // 77 {-0.06, 6, 0, 0, 0}, // 77
{-0.07, 13, -3, 0}, // 78 {-0.07, 13, -3, 0, 0}, // 78
{0.02, 13, 3, 0}, // 79 {0.02, 13, 3, 0, 0}, // 79
}; };
/** /**
* @brief get_sensor_location - return pointer to sensor_data for given sensor * @brief get_sensor_location - search given sensor in `sensors` table
* @param Nct - controller number * @param Nct - controller number
* @param Nch - channel number * @param Nch - channel number
* @param Ns - sensor number * @param Ns - sensor number
* @return * @return pointer to sensor_data for given sensor
*/ */
const sensor_data *get_sensor_location(int Nct, int Nch, int Ns){ const sensor_data *get_sensor_location(int Nct, int Nch, int Ns){
if(Nct < 1 || Nct > NCTRLR_MAX || Nch > NCHANNEL_MAX || Ns > 1){ if(Nct < 1 || Nct > NCTRLR_MAX || Nch > NCHANNEL_MAX || Ns > 1){
@ -204,6 +204,106 @@ const sensor_data *get_sensor_location(int Nct, int Nch, int Ns){
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; coords=(%d, %d, %d)\n", s->dt, 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'
static char *omitspaces(char *str){
char ch;
do{
ch = *str;
if(!ch) return NULL; // EOL
if(ch == ' ' || ch == '\t'){
++str;
continue;
}
if(ch == '#' || ch == '\n'){
return NULL; // comment
}
return str;
}while(1);
return NULL;
}
/**
* @brief read_adj_file - try to read file with thermal adjustments
* @param fname - filename
* @return 0 if all OK
* thermal adjustments file should have simple structure:
* No of sensor (like in output format, e.g. 561) and Tcorr value (Treal = T - Tcorr)
* all data after # ignored
*/
int read_adj_file(char *fname){
double Tadj[NSENSORS] = {0,};
if(!fname){
WARNX("read_adj_file(): filename missing");
return 1;
}
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');
char *nextchar = omitspaces(adjf);
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);
}
nextchar = omitspaces(endptr);
if(!nextchar){
WARNX("There's no temperature data after sensor's number");
goto reperr;
}
double t = strtod(nextchar, &endptr);
if(endptr == nextchar || !endptr){
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 #)");
goto reperr;
}
cont:
if(!eol) break;
adjf = eol + 1;
++strnum;
}
My_munmap(buf);
for(int i = 0; i < NSENSORS; ++i){
if(fabs(Tadj[i]) > DBL_EPSILON){
printf("Tadj[%d] = %g\n", i, Tadj[i]);
}
sensors[i].Tadj = Tadj[i];
}
return 0;
reperr:
red("Error in string %d:\n", strnum);
printf("%s\n", adjf);
putlog("Erroneous log file %s in line %d", fname, strnum);
return 1;
}

View File

@ -23,14 +23,19 @@
#define NCTRLR_MAX (5) #define NCTRLR_MAX (5)
// max number of channel // max number of channel
#define NCHANNEL_MAX (7) #define NCHANNEL_MAX (7)
// total amount of sensors @ the mirror
#define NSENSORS (NCTRLR_MAX*2*(NCHANNEL_MAX+1))
typedef struct{ typedef struct{
float dt; float dt;
int X; int X;
int Y; int Y;
int Z; int Z;
float Tadj;
} sensor_data; } sensor_data;
const sensor_data *get_sensor_location(int Nct, int Nch, int Ns); const sensor_data *get_sensor_location(int Nct, int Nch, int Ns);
int read_adj_file(char *fname);
#endif // SENS_PLACE_H__ #endif // SENS_PLACE_H__

View File

@ -282,10 +282,10 @@ Item quick_select(Item *idata, int n){
static void process_T(){ static void process_T(){
int i, N, p, Num = 0; int i, N, p, Num = 0;
time_t tmeasmax = 0; time_t tmeasmax = 0;
double arr[128]; double arr[NSENSORS];
// mean temperatures over 15 scans // mean temperatures over 15 scans
static double Tmean[2][NCHANNEL_MAX+1][NCTRLR_MAX+1]; static double Tmean[2][NCHANNEL_MAX+1][NCTRLR_MAX+1];
static int Nmean; // amount of measurements for Tmean static int Nmean[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], Nmeanmax; // amount of measurements for Tmean
// get statistics // get statistics
poll_sensors(0); // poll N2 poll_sensors(0); // poll N2
// scan over controllers on mirror & calculate median // scan over controllers on mirror & calculate median
@ -304,32 +304,35 @@ static void process_T(){
} }
// calculate mean // calculate mean
double Tmed = quick_select(arr, Num); double Tmed = quick_select(arr, Num);
double Tbot = Tmed - 3., Ttop = Tmed + 3.; double Tbot = Tmed - 10., Ttop = Tmed + 10.;
DBG("Got %d values, Tmed=%g", Num, Tmed); DBG("Got %d values, Tmed=%g", Num, Tmed);
// throw out all more than +-3degrC and calculate meanT // throw out all more than +-10degrC and calculate meanT
Num = 0; Num = 0;
double Tsum = 0.; double Tsum = 0.;
for(i = 1; i <= NCTRLR_MAX; ++i){ for(i = 1; i <= NCTRLR_MAX; ++i){
for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){ for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){
double T = t_last[p][N][i]; double T = t_last[p][N][i];
if(T > Ttop || T < Tbot || tmeasmax - tmeasured[p][N][i] > 1800){ if(T > Ttop || T < Tbot || tmeasmax - tmeasured[p][N][i] > 1800){ // not longer than 3 minutes ago!
t_last[p][N][i] = -300.; t_last[p][N][i] = -300.;
Tmean[p][N][i] = -3e9;
}else{ }else{
++Num; Tsum += T; ++Num; Tsum += T;
Tmean[p][N][i] += T; Tmean[p][N][i] += T;
++Nmean[p][N][i];
} }
} }
} }
// make graphics // make graphics
if(G->savepath){ if(G->savepath){
if(++Nmean == GRAPHS_AMOUNT){ if(++Nmeanmax == GRAPHS_AMOUNT){
for(i = 1; i <= NCTRLR_MAX; ++i)for(p = 0; p < 2; ++p)for(N = 0; N <= NCHANNEL_MAX; ++ N){ for(i = 1; i <= NCTRLR_MAX; ++i)for(N = 0; N <= NCHANNEL_MAX; ++ N)for(p = 0; p < 2; ++p){
Tmean[p][N][i] /= Nmean; if(Nmean[p][N][i]){
Tmean[p][N][i] /= Nmean[p][N][i];
Nmean[p][N][i] = 0;
}else Tmean[p][N][i] = -300.; // no data
} }
plot(Tmean, G->savepath); plot(Tmean, G->savepath);
memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1)); memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1));
Nmean = 0; Nmeanmax = 0;
} }
} }
meanT = Tsum / Num; meanT = Tsum / Num;
@ -384,7 +387,7 @@ static void daemon_(int sock){
buf = &ptrs[sdata->Z]; len = &lens[sdata->Z]; buf = &ptrs[sdata->Z]; len = &lens[sdata->Z];
// iNp x y T(corrected) time // iNp x y T(corrected) time
l = snprintf(*buf, *len, "%d%d%d\t%d\t%d\t%.2f\t%ld\n", i, N, p, l = snprintf(*buf, *len, "%d%d%d\t%d\t%d\t%.2f\t%ld\n", i, N, p,
sdata->X, sdata->Y, T - sdata->dt, tmeasured[p][N][i]); sdata->X, sdata->Y, T - sdata->dt - sdata->Tadj, tmeasured[p][N][i]);
} }
*len -= l; *len -= l;
*buf += l; *buf += l;

View File

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

View File

@ -133,7 +133,7 @@ static int parse_answer(char *buf, int N){
//DBG("sensor #%d", v); //DBG("sensor #%d", v);
//if(v < 0 || v > 81) return 0; //if(v < 0 || v > 81) return 0;
i = v/10; v -= i*10; i = v/10; v -= i*10;
if(i < 0 || i > NCTRLR_MAX) return 0; if(i < 0 || i > NCHANNEL_MAX) return 0;
//DBG("i=%d, v=%d", i,v); //DBG("i=%d, v=%d", i,v);
if((v & 1) != v) return 0; // should be only 0 or 1 if((v & 1) != v) return 0; // should be only 0 or 1
if(*buf != '=' ) return 0; if(*buf != '=' ) return 0;
@ -144,6 +144,7 @@ static int parse_answer(char *buf, int N){
return 0; return 0;
} }
t_last[v][i][N] = ((double)T) / 100.; t_last[v][i][N] = ((double)T) / 100.;
DBG("T(%d_%d%d)=%g", N, i, v, T/100.);
tmeasured[v][i][N] = time(NULL); tmeasured[v][i][N] = time(NULL);
return 1; return 1;
} }
@ -196,7 +197,7 @@ int poll_sensors(int N){
} }
int ngot = 0; int ngot = 0;
double t0 = dtime(); double t0 = dtime();
while(dtime() - t0 < T_POLLING_TMOUT && ngot < 16){ // timeout reached or got data from all while(dtime() - t0 < T_POLLING_TMOUT && ngot < 2*(NCHANNEL_MAX+1)){ // timeout reached or got data from all
if((ans = read_string())){ // parse new data if((ans = read_string())){ // parse new data
//DBG("got %s", ans); //DBG("got %s", ans);
if(*ans == CMD_MEASURE_T){ // data from sensor if(*ans == CMD_MEASURE_T){ // data from sensor

View File

@ -204,7 +204,7 @@ mmapbuf *My_mmap(char *filename){
void My_munmap(mmapbuf *b){ void My_munmap(mmapbuf *b){
if(munmap(b->data, b->len)){ if(munmap(b->data, b->len)){
/// "îÅ ÍÏÇÕ munmap" /// "îÅ ÍÏÇÕ munmap"
ERR(_("Can't munmap")); WARN(_("Can't munmap"));
} }
FREE(b); FREE(b);
} }
@ -290,12 +290,12 @@ void restore_tty(){
#endif #endif
// init: // init:
void tty_init(char *comdev){ void tty_init(char *comdev){
DBG("\nOpen port %s ...\n", comdev); DBG("\nOpen port %s ...", comdev);
do{ do{
comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK); comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK);
}while (comfd == -1 && errno == EINTR); }while (comfd == -1 && errno == EINTR);
if(comfd < 0){ if(comfd < 0){
WARN("Can't use port %s\n",comdev); WARN("Can't use port %s",comdev);
signals(-1); // quit? signals(-1); // quit?
} }
// make exclusive open // make exclusive open
@ -321,7 +321,7 @@ void tty_init(char *comdev){
WARN(_("Can't set settings")); WARN(_("Can't set settings"));
signals(-1); signals(-1);
} }
DBG(" OK\n"); DBG(" OK");
} }
/** /**