diff --git a/src/netdaemon/Commands_list b/src/netdaemon/Commands_list index 2b2cc4a..4aaba96 100644 --- a/src/netdaemon/Commands_list +++ b/src/netdaemon/Commands_list @@ -1,6 +1,7 @@ ## Serial interface commands (ends with '\n'), small letter for only local processing: - **0...7** send message to Nth controller, not broadcast (after number should be CAN command) - **@** set/reset debug mode +- **A** allow given node to speak - **a** get raw ADC values - **B** send dummy CAN messages to broadcast address - **b** get/set CAN bus baudrate @@ -9,20 +10,21 @@ - **d** get current CAN address of device - **Ee** end temperature scan - **Ff** turn sensors off -- **g** group (sniffer) CAN mode (print to USB terminal all incoming CAN messages with alien IDs) +- **g** sniffer CAN mode (print to USB terminal all incoming CAN messages with alien IDs) - **Hh** switch I2C to high speed (100kHz) - **Ii** (re)init sensors - **Jj** get MCU temperature - **Kk** get values of U and I - **Ll** switch I2C to low speed (default, 10kHz) -- **Mm** change master id to 0 (**m**) / broadcast (**M**) - **N** get build number - **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands are local!) - **P** ping everyone over CAN - **Qq** get system time - **Rr** reinit I2C +- **S** shut up given node - **s** send CAN message (format: ID data[0..8], dec, 0x - hex, 0b - binary) - **Tt** start single temperature measurement +- **U** USB status of given node (0 - off) - **u** unique ID (default) CAN mode - **Vv** very low speed - **Xx** go into temperature scan mode diff --git a/src/netdaemon/Readme.md b/src/netdaemon/Readme.md index ed9dd88..3d928f3 100644 --- a/src/netdaemon/Readme.md +++ b/src/netdaemon/Readme.md @@ -1,7 +1,12 @@ BTA mirror temperature network daemon ================== -Gather information from temperature sensors and send it over ethernet by network request like +Gather information from temperature sensors and send it over ethernet by network request. + +## Protocol + +Request format over http: + hostname:4444/Tx where x is 0 for upper sensors, 1 for lower and 2 for T measured by main controller. hostname:4444/Tmean returns mean temperature @@ -13,15 +18,18 @@ Answer format: "ID X Y T t", where - T is measured temperature (degrees Celsium), - t is UNIX-time of last measurement. +Also you can connect to server by regular INET socket through the same port. Send T0, T1, T2 or Tmean to get data. +After data sending server close socket. + To look graph over gnuplot utility collect gnuplot javascript files in subdirectory js of web-server images storing directory, copy there script 'plot' and run service as netdaemon -g -s /path/to/web /path/to/log Every 15 minutes it will calculate average values of thermal data and plot three graphs: -T0.html with top temperatures, T1.html with bottom and Tgrad.html with their differences (T0-T1). +T0.html with top temperatures and T1.html with bottom. -** Signals +## Signals SIGUSR1 - reread temperatures adjustment file diff --git a/src/netdaemon/socket.c b/src/netdaemon/socket.c index 5396ef9..0ab53a2 100644 --- a/src/netdaemon/socket.c +++ b/src/netdaemon/socket.c @@ -22,6 +22,7 @@ */ #include // inet_ntop #include // INT_xxx +#include // isfinite, sqrt #include // addrinfo #include #include // pthread_kill @@ -197,6 +198,7 @@ static void *handle_socket(void *asock){ } pthread_mutex_unlock(&mutex); }else if(strncmp("Tmean", found, 5) == 0){ // send user meanT + if(!isfinite(meanT) || meanT < ABS_ZERO_T) break; // wrong value L = snprintf(tbuf, 128, "%.2f\n", meanT); if(L != write(sock, tbuf, L)) WARN("write()"); }else if(strncmp("ReBoOt", found, 6) == 0){ @@ -300,6 +302,19 @@ Item quick_select(Item *idata, int n){ #undef PIX_SORT #undef ELEM_SWAP +// get RMS +double sigma(double *data, int n){ + if(n < 2) return 0.; + double sum = 0., sum2 = 0.; + for(int i = 0; i < n; ++i){ + double d = data[i]; + sum += d; + sum2 += d*d; + } + sum /= n; sum2 /= n; + return sqrt(sum2 - sum*sum); +} + static void process_T(){ int i, N, p, Num = 0; time_t tmeasmax = 0; @@ -325,22 +340,24 @@ static void process_T(){ } // calculate mean double Tmed = quick_select(arr, Num); - double Tbot = Tmed - 10., Ttop = Tmed + 10.; - DBG("Got %d values, Tmed=%g, tmeasmax=%zd", Num, Tmed, tmeasmax); - // throw out all more than +-10degrC and calculate meanT + double rms3 = 3. * sigma(arr, Num); + // bounds: +-3RMS + double Tbot = Tmed - rms3, Ttop = Tmed + rms3; + DBG("Got %d values, Tmed=%g, Trms=%g, tmeasmax=%zd", Num, Tmed, rms3/3., tmeasmax); + // throw out all more than +-3RMS and calculate meanT Num = 0; double Tsum = 0.; - // remove bad/old values of N2 controller + // remove bad/old values for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){ if(tmeasmax - tmeasured[p][N][0] > OLDESTTM){ // not longer than 3 minutes ago! - t_last[p][N][0] = -300.; + t_last[p][N][0] = WRONG_T; } } for(i = 1; i <= NCTRLR_MAX; ++i){ for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){ double T = t_last[p][N][i]; if(T > Ttop || T < Tbot || tmeasmax - tmeasured[p][N][i] > OLDESTTM){ // not longer than 3 minutes ago! - t_last[p][N][i] = -300.; + t_last[p][N][i] = WRONG_T; }else{ DBG("t_last[%d][%d][%d]=%.1f, measuredt=%zd", p, N, i, T, tmeasured[p][N][i]); ++Num; Tsum += T; @@ -357,16 +374,15 @@ static void process_T(){ 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 + }else Tmean[p][N][i] = WRONG_T; // 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; } } - meanT = Tsum / Num; + if(Num) meanT = Tsum / Num; + else meanT = WRONG_T; // no good measurements DBG("got %d, mean: %g\n\n", Num, meanT); } @@ -402,7 +418,8 @@ static void daemon_(int sock){ tgot = dtime(); process_T(); // get new temperatures & throw out bad results for(i = 0; i <= NCTRLR_MAX; ++i){ // scan over controllers - for(int N = 0; N <= NCHANNEL_MAX; ++N) for(int p = 0; p < 2; ++p){ + int N, p; + for(N = 0; N <= NCHANNEL_MAX; ++N) for(p = 0; p < 2; ++p){ double T = t_last[p][N][i]; char **buf; size_t *len; diff --git a/src/netdaemon/socket.h b/src/netdaemon/socket.h index 1672b94..adc01e7 100644 --- a/src/netdaemon/socket.h +++ b/src/netdaemon/socket.h @@ -27,6 +27,11 @@ // timeout for socket closing #define SOCKET_TIMEOUT (5.0) +// absolute zero: all T < ABS_ZERO_T are wrong +#define ABS_ZERO_T (-273.15) +// undoubtedly wrong T +#define WRONG_T (-300.) + void daemonize(char *port); const char *gotstr(int N); void TurnOFF(); diff --git a/src/netdaemon/tempadj.txt b/src/netdaemon/tempadj.txt index e0761e6..326e405 100644 --- a/src/netdaemon/tempadj.txt +++ b/src/netdaemon/tempadj.txt @@ -1,4 +1,5 @@ #No dT (Treal = T - dT) +111 0.1 251 -0.7 320 0.12 330 0.15