je vais tout casser ?
This commit is contained in:
commit
975e501d9b
18
.gitignore
vendored
18
.gitignore
vendored
@ -2,9 +2,25 @@ a.out
|
||||
*.o
|
||||
fake-values
|
||||
essai
|
||||
foo.dat
|
||||
serial/t
|
||||
doc/*.toc doc/*.log doc/*.aux doc/*.pdf
|
||||
core/t
|
||||
core/*.a
|
||||
|
||||
doc/*.toc
|
||||
doc/*.log
|
||||
doc/*.aux
|
||||
doc/*.pdf
|
||||
doc/*.idx
|
||||
doc/*.ilg
|
||||
doc/*.ind
|
||||
|
||||
*/*.dat
|
||||
|
||||
rrdb/*.png
|
||||
serial/*.png
|
||||
|
||||
viz/curses/t
|
||||
viz/gnuplot/*.png
|
||||
viz/*.a
|
||||
|
||||
|
26
BUILD.txt
Normal file
26
BUILD.txt
Normal file
@ -0,0 +1,26 @@
|
||||
+--------------------------------+
|
||||
| how to build the dd2-monitor ? |
|
||||
+--------------------------------+
|
||||
|
||||
First step, build some parts of the core library :
|
||||
|
||||
$ cd core
|
||||
$ make t
|
||||
$ ./t -v
|
||||
$ cd ..
|
||||
|
||||
Then you must have datas for working on. One source of datas
|
||||
is the four values who came from the Arduino over serial line.
|
||||
At this time, you must look at the configuration file.
|
||||
|
||||
$ cd serial
|
||||
$ make t
|
||||
|
||||
Have a look at the 'essai.sh' file for an example of simple
|
||||
usage of the serial input. For generating all that numbers,
|
||||
you have to run some code on the Arduino mega. Sources are
|
||||
in the simulator/ folder.
|
||||
|
||||
|
||||
|
||||
|
19
Makefile
19
Makefile
@ -2,19 +2,20 @@
|
||||
# must be run with gnu make
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
|
||||
CCOPT = -Wall -g
|
||||
CC = gcc
|
||||
CCOPT = -Wall -g
|
||||
CLIB = core/libdd2m-core.a viz/libdd2m-viz.a
|
||||
|
||||
all: essai fake-values
|
||||
|
||||
essai: essai.c funcs.o Makefile
|
||||
gcc ${CCOPT} $< funcs.o -o $@
|
||||
# ---------------------------------------------
|
||||
|
||||
O = serial/serial.o serial/funcs.o
|
||||
|
||||
funcs.o: funcs.c funcs.h Makefile
|
||||
gcc ${CCOPT} -c $<
|
||||
essai: essai.c Makefile $(CLIB)
|
||||
$(CC) ${CCOPT} $< $(CLIB) ${O} -lncurses -o $@
|
||||
|
||||
fake-values: fake-values.c funcs.o Makefile
|
||||
gcc ${CCOPT} $< funcs.o -o $@
|
||||
fake-values: fake-values.c Makefile $(CLIB)
|
||||
$(CC) ${CCOPT} $< $(CLIB) -o $@
|
||||
|
||||
# ---------------------------------------------
|
||||
|
22
README.md
22
README.md
@ -5,13 +5,35 @@ de _monitoring_ pour le futur Phytotron du Tetalab.
|
||||
|
||||
Le but premier de ce système est de faciliter la mise au point d'un
|
||||
automate de contrôle de l'enceinte thermostatée. Nous devrons
|
||||
<<<<<<< HEAD
|
||||
surveiller température et humidité du dd2, et température du
|
||||
confinement biologique.
|
||||
=======
|
||||
surveiller température et humidité du dd2,
|
||||
éclairage et température du confinement biologique.
|
||||
>>>>>>> b47e467d21cec6ee688b4407d3ec54fa33e67ba6
|
||||
|
||||
Pour en savoir plus sur ce passionnant projet, il y a le canal IRC
|
||||
`#tetalab` sur le réseau Freenode et/ou les rencontres du mercredi
|
||||
soir au DD2, à Mixart-Myrys.
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
Et aussi https://pad.tetalab.org/p/dd2-monitoring
|
||||
|
||||
# WTF status
|
||||
|
||||
Seriazl : Le `read` bloquant ne bloque pas. Ça craint grave. La recherche
|
||||
du workaround avance.
|
||||
|
||||
Premier essai RRD : ça marchote...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
>>>>>>> b47e467d21cec6ee688b4407d3ec54fa33e67ba6
|
||||
|
||||
|
||||
|
||||
|
36
core/Makefile
Normal file
36
core/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
#
|
||||
# dd2 monitoring
|
||||
#
|
||||
# build the core functions, use with care
|
||||
#
|
||||
|
||||
|
||||
COPT = -Wall -fpic -g -DDEBUG_LEVEL=0
|
||||
OBJS = lut1024f.o parseconf.o utils.o sysmetrics.o
|
||||
DEPS = Makefile
|
||||
ALIB = libdd2m-core.a
|
||||
# ---------------------------------------------------
|
||||
|
||||
${ALIB}: ${OBJS}
|
||||
ar r $@ $?
|
||||
|
||||
lut1024f.o: lut1024f.c lut1024.h ${DEPS}
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
parseconf.o: parseconf.c config.h ${DEPS}
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
utils.o: utils.c utils.h ${DEPS}
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
sysmetrics.o: sysmetrics.c ${DEPS}
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
# ---------------------------------------------------
|
||||
|
||||
t: t.c ${ALIB} lut1024.h config.h utils.h ${DEPS}
|
||||
gcc -Wall $< ${ALIB} -o $@
|
||||
|
||||
foo.lut1024f: mklut.pl Makefile
|
||||
./mklut.pl quux > $@
|
||||
|
24
core/config.h
Normal file
24
core/config.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* config.h
|
||||
*/
|
||||
|
||||
#define SZ_STRINGS 200
|
||||
|
||||
typedef struct {
|
||||
|
||||
int valid;
|
||||
|
||||
char *input_device;
|
||||
int input_speed;
|
||||
|
||||
char *eyecandy_banner;
|
||||
|
||||
} Configuration;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int set_default_config(Configuration *cfg);
|
||||
int parse_config(char *fname, int flags);
|
||||
int show_config(char *title);
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
16
core/dd2-monitor.conf
Normal file
16
core/dd2-monitor.conf
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# experimental config file
|
||||
#
|
||||
|
||||
# --------------------------------------------------
|
||||
# serial input from the control cpu
|
||||
|
||||
input_device s /dev/ttyACM0
|
||||
input_speed i 9600
|
||||
|
||||
# --------------------------------------------------
|
||||
# some values for the eyecandy displays
|
||||
|
||||
eyecandy_banner s hacked by tTh
|
||||
|
||||
# --------------------------------------------------
|
17
core/lut1024.h
Normal file
17
core/lut1024.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* LUT 1024 - DEALING WITH DISCRETE VALUES
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
int flags;
|
||||
float vals[1024];
|
||||
} Lut1024f;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int slurp_lut1024f(FILE *fp, Lut1024f *where, int notused);
|
||||
int load_lut1024f(char *fname, Lut1024f *where, int notused);
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
70
core/lut1024f.c
Normal file
70
core/lut1024f.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* LUT 1024 -> FLOAT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lut1024.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int slurp_lut1024f(FILE *fp, Lut1024f *where, int notused)
|
||||
{
|
||||
int count, foo;
|
||||
|
||||
for(count=0; count<1024; count++) {
|
||||
foo = fscanf(fp, "%f", &where->vals[foo]);
|
||||
if (1 != foo) {
|
||||
fprintf(stderr, "%s: bad read %d\n", __func__, foo);
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int load_lut1024f(char *fname, Lut1024f *where, int notused)
|
||||
{
|
||||
FILE *fplut;
|
||||
char firstline[100];
|
||||
char label[] = "LUT1024F";
|
||||
int foo;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintg(stderr, ">>> %s ( '%s' %p %d )\n", __func__,
|
||||
fname, where, notused);
|
||||
#endif
|
||||
|
||||
if (NULL==(fplut=fopen(fname, "r"))) {
|
||||
perror(fname);
|
||||
return -2;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: getting first line\n", __func__);
|
||||
|
||||
if (NULL==fgets(firstline, 20, fplut)) {
|
||||
fprintf(stderr, "%s: nothing to read from %s\n",
|
||||
__func__, fname);
|
||||
return -3;
|
||||
}
|
||||
|
||||
foo = strncmp(label, firstline, sizeof(label)-1);
|
||||
if (foo) {
|
||||
fprintf(stderr, "%s: bad label [%s]\n", __func__, firstline);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
foo = slurp_lut1024f(fplut, where, 0);
|
||||
|
||||
fclose(fplut);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
10
core/mklut.pl
Executable file
10
core/mklut.pl
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
my $foo;
|
||||
|
||||
print "LUT1024F\n";
|
||||
|
||||
for ($foo=0; $foo<1024; $foo++) {
|
||||
print rand()*3.30, "\n";
|
||||
}
|
||||
0;
|
112
core/parseconf.c
Normal file
112
core/parseconf.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* core/parseconf.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
extern int verbosity;
|
||||
extern Configuration config;
|
||||
|
||||
#define CMP(a) (!strcmp(keyptr, a))
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int parse_config(char *fname, int flags)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[SZ_STRINGS+1],
|
||||
*keyptr, *typeptr, *cptr;
|
||||
int numligne;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, ">>> %s ( '%s' $%x )\n", fname, flags);
|
||||
#endif
|
||||
|
||||
config.valid = 49;
|
||||
|
||||
if (NULL==(fp=fopen(fname, "r"))) {
|
||||
perror(fname);
|
||||
return -2;
|
||||
}
|
||||
|
||||
numligne = 0;
|
||||
|
||||
while (fgets(line, SZ_STRINGS, fp))
|
||||
{
|
||||
numligne++;
|
||||
if ('\0'==line[0]) {
|
||||
fprintf(stderr, "%s : short read line %d\n",
|
||||
fname, numligne);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* massage the end of line */
|
||||
line[strlen(line)-1] = '\0'; /* kill EOL */
|
||||
if (verbosity) {
|
||||
fprintf(stderr, "%3d :\t%s\n", numligne, line);
|
||||
}
|
||||
|
||||
/* seek for the first token in this line */
|
||||
if (NULL==(keyptr = strtok(line, " \t"))) {
|
||||
/* Got an empty line */
|
||||
continue;
|
||||
}
|
||||
/* skip comments */
|
||||
if ('#'==*keyptr) continue;
|
||||
/* seek for the type field */
|
||||
if (NULL==(typeptr = strtok(NULL, " \t"))) {
|
||||
/* we can(t get a type flag ? wtf ? */
|
||||
fprintf(stderr, "ERROR line %d : no type\n", numligne);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(verbosity)
|
||||
fprintf(stderr, "[%s] type %s\n", keyptr, typeptr);
|
||||
|
||||
if CMP("abort") {
|
||||
fprintf(stderr, "abort in config file\n");
|
||||
}
|
||||
|
||||
if (CMP("input_device")) {
|
||||
config.input_device = strdup(strtok(NULL, " \t"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CMP("input_speed")) {
|
||||
config.input_speed = atoi(strtok(NULL, " \t"));
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "input speed = %d\n", config.input_speed);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (CMP("eyecandy_banner")) {
|
||||
config.eyecandy_banner = strdup(strtok(NULL, " \t"));
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int show_config(char *title)
|
||||
{
|
||||
|
||||
if (verbosity) {
|
||||
printf("********** %s **********\n", title);
|
||||
}
|
||||
|
||||
printf("valid : %d\n", config.valid);
|
||||
printf("input device : %s\n", config.input_device);
|
||||
printf("input speed : %d\n", config.input_speed);
|
||||
|
||||
puts("");
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
38
core/sysmetrics.c
Normal file
38
core/sysmetrics.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* core/sysmetrics.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sysmetrics.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
int get_loadavg(float *where)
|
||||
{
|
||||
FILE *fp;
|
||||
float loads[3];
|
||||
int foo;
|
||||
|
||||
if ( ! (fp=fopen("/proc/loadavg", "r")) ) {
|
||||
perror("read loadavg");
|
||||
return -1;
|
||||
}
|
||||
|
||||
foo = fscanf(fp, "%f %f %f", loads, loads+1, loads+2);
|
||||
if (3 != foo) fprintf(stderr, "%s : read %d vals\n", __func__, foo);
|
||||
|
||||
memcpy(where, loads, 3 * sizeof(float));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
4
core/sysmetrics.h
Normal file
4
core/sysmetrics.h
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
int get_loadavg(float *where);
|
||||
|
73
core/t.c
Normal file
73
core/t.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* main de test des core functions
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "lut1024.h"
|
||||
#include "config.h"
|
||||
#include "sysmetrics.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
Configuration config;
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int essai_sysmetrics(int k)
|
||||
{
|
||||
float fvalues3[3];
|
||||
int foo;
|
||||
|
||||
foo = get_loadavg(fvalues3);
|
||||
if (foo) {
|
||||
fprintf(stderr, "err get load avg %d\n", foo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("load avg %f %f %f\n", fvalues3[0], fvalues3[1], fvalues3[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int foo, opt;
|
||||
char *conffile = "dd2-monitor.conf";
|
||||
|
||||
fprintf(stderr, "+\n+ DD2 MONITOR\n+\n");
|
||||
|
||||
/* set some default values */
|
||||
verbosity = 0;
|
||||
|
||||
|
||||
while ((opt = getopt(argc, argv, "v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v': verbosity++; break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s : uh ?", argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
foo = parse_config(conffile, 0);
|
||||
fprintf(stderr, "parse_config(%s) -> %d\n\n", conffile, foo);
|
||||
show_config("foo");
|
||||
|
||||
essai_sysmetrics(0);
|
||||
/*
|
||||
foo = load_lut1024f("foo.lut1024f", NULL, 1);
|
||||
fprintf(stderr, "chargement de la lut --> %d\n\n", foo);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* funcs.c
|
||||
* core/utils.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -9,8 +9,6 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "funcs.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
@ -25,9 +23,11 @@ return v1 ^ v2;
|
||||
/* --------------------------------------------------------------- */
|
||||
int random1000(int type)
|
||||
{
|
||||
int value;
|
||||
if (verbosity)
|
||||
fprintf(stderr, ">>> %s(%d)\n", __func__, type);
|
||||
int value, foo;
|
||||
|
||||
#if DEBUG_LEVEL > 1
|
||||
fprintf(stderr, ">>> %s(%d)\n", __func__, type);
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
@ -36,6 +36,12 @@ switch (type) {
|
||||
case 1:
|
||||
value = (rand()%1000 + rand()%1000) / 2;
|
||||
break;
|
||||
case 4:
|
||||
value = 0;
|
||||
for (foo=0; foo<4; foo++)
|
||||
value += rand() % 1000;
|
||||
value /= 4;
|
||||
break;
|
||||
default:
|
||||
value = -1;
|
||||
break;
|
||||
@ -43,9 +49,7 @@ switch (type) {
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
double dtime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
@ -56,28 +60,4 @@ if (foo) fprintf(stderr, "got %d in %s\n", foo, __func__);
|
||||
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec / 1e6;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
int get_loadavg(double *where)
|
||||
{
|
||||
FILE *fp;
|
||||
double loads[3];
|
||||
int foo;
|
||||
|
||||
if ( ! (fp=fopen("/proc/loadavg", "r")) ) {
|
||||
perror("read loadavg");
|
||||
return -1;
|
||||
}
|
||||
|
||||
foo = fscanf(fp, "%lf %lf %lf", loads, loads+1, loads+2);
|
||||
if (3 != foo) fprintf(stderr, "%s : read %d vals\n", __func__, foo);
|
||||
|
||||
memcpy(where, loads, 3 * sizeof(double));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
8
core/utils.h
Normal file
8
core/utils.h
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* core/utils.h
|
||||
*/
|
||||
|
||||
int seed_my_rand(int foo);
|
||||
int random1000(int type);
|
||||
|
||||
double dtime(void);
|
7
core/wtf.txt
Normal file
7
core/wtf.txt
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
|
||||
Il est temps de se reprendre en main
|
||||
|
||||
|
||||
|
81
doc/automate.tex
Normal file
81
doc/automate.tex
Normal file
@ -0,0 +1,81 @@
|
||||
\section{Automate} \index{automate} \label{automate}
|
||||
|
||||
L'automate qui contrôle les fonctions vitales des petites
|
||||
\textit{Pyrocystis Fusiformis} est basé sur un Arduino Mega\index{mega},
|
||||
qui a été choisi pour sa profusion d'entrées sorties\index{i/o}.
|
||||
Il va remplir plusieurs fonctions mises au point les unes et les autres.
|
||||
|
||||
Dans un premier temps, le logiciel sera développé avec l'\textsl{IDE}
|
||||
standard de l'Arduiono, malgré ses limitations.
|
||||
Il existe des solutions alternatives à base de \texttt{makefile}, que
|
||||
nous découvrirons un jour, si le besoin s'en fait sentir.
|
||||
|
||||
Ce lo
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Dialogue}
|
||||
|
||||
Le but étant d'avoir un système
|
||||
\textsl{standalone}\footnote{lowcost and easytouse ?}, le dialogue
|
||||
avec les humains extérieur sera plus que limité en fonctionnement
|
||||
courant.
|
||||
|
||||
Pour la configuration, nous allons créer une \textsc{CLI}\index{cli}
|
||||
rudimentaire qui sera accessible par le port USB et un émulateur
|
||||
de terminal\footnote{Minicom, Putty...}.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Température} \index{temperature}
|
||||
|
||||
Les capteurs utilisés sont des LM35\index{LM35}, à sortie analogique
|
||||
entre 0 et 5v pour une gamme de température de 0 à ??? degrés Celsius.
|
||||
|
||||
Le convertisseur \small{A/D} a une résolution de 10 bits, qu'il
|
||||
est possible d'augmenter en changeant son Vref, soit pour une
|
||||
référence externe, soit pour une référence interne à 1.1 V.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Voyants}
|
||||
|
||||
Il faut \textbf{toujours} intégrer dans un projet une gestion avancée
|
||||
des \textsc{led}\index{LED} qui clignotent avec entrain pour raconter
|
||||
la vie interne de la machinerie.
|
||||
|
||||
Une paire Rouge/Bleue indiquera les sorties de l'intervalle
|
||||
de température pré-programmé.
|
||||
Une \textsc{led} orange clignotante indiquera une erreur
|
||||
en s'exprimant en code Morse.
|
||||
|
||||
Quand à la \textsc{led} verte, elle sera là pour ne rien dire de précis,
|
||||
mais avec brio.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Chauffage} \index{chauffage}
|
||||
|
||||
En première approche, un choix simple a été fait~: nous allons
|
||||
utiliser un chauffage intégré d'aquarium en de basant d'abord
|
||||
sur son thermostat intégré.
|
||||
|
||||
Si ce n'est pas satisfaisant, pour diverses raisons (matériel
|
||||
chinois à 3 balles, par exemple),
|
||||
nous serons obligés de commander nous-même ce chauffage.
|
||||
|
||||
C'est à ce moment que les choses deviennent sérieuses, il va
|
||||
falloir commuter du 230v, tension assez mortelle dans les faits.
|
||||
Une solution à base d'opto-coupleur semble s'imposer.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Refroidissement}.
|
||||
|
||||
Puisque l'enceinte choisi est un frigorifique de
|
||||
récupération\footnote{Merci DomDom :)}, nous pourrons utiliser son
|
||||
groupe froid. Comme pour le chauffage, nous sommes sur du 230v.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
\documentclass[a4paper,12pt]{article}
|
||||
\documentclass[a4paper,11pt]{article}
|
||||
|
||||
% \listfiles % pour le debug
|
||||
|
||||
@ -8,13 +7,14 @@
|
||||
\usepackage[T1]{fontenc}
|
||||
% XXX \usepackage{lipsum}
|
||||
\usepackage{makeidx}
|
||||
\usepackage{listings}
|
||||
% \usepackage{color}
|
||||
% \usepackage{url}
|
||||
\usepackage{xspace}
|
||||
\usepackage[verbose]{layout}
|
||||
|
||||
\makeindex
|
||||
\setlength{\parskip}{0.25cm plus 0.25cm}
|
||||
% \setlength{\parskip}{0.16cm plus 0.16cm}
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\title{DD2 Monitoring}
|
||||
@ -25,6 +25,12 @@
|
||||
|
||||
\pagebreak
|
||||
|
||||
% \setlength{\parskip}{0.01cm plus 0.01cm}
|
||||
\tableofcontents
|
||||
% \setlength{\parskip}{0.16cm plus 0.16cm}
|
||||
|
||||
\pagebreak
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Introduction}
|
||||
@ -41,45 +47,85 @@ arrivons parfois à le faire.
|
||||
|
||||
La première étape sera donc la mise au point d'un \textsl{cadriciel}
|
||||
permettant d'essayer diverses options en se basant sur une conception
|
||||
modulaire de l'ensemble.
|
||||
modulaire de l'ensemble. Une grosse partie sera écrite en C\index{C},
|
||||
avec d'éventuels modules en langages de script :
|
||||
Perl\index{Perl}, Awk\index{Awk}, Bash\index{Bash}\dots
|
||||
|
||||
Les valeurs à mesurer étant de diverses natures, nous aurons l'occasion
|
||||
de découvrir plein de capteurs différents : température, humidité,
|
||||
\texttt{pH}, transparence, lumière, vibrations\dots
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\vspace{4cm}
|
||||
|
||||
Bonne lecture.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
% ===================================================================
|
||||
|
||||
\pagebreak
|
||||
\section{Présentation générale}
|
||||
|
||||
\subsection{Capteurs} \index{capteurs}
|
||||
|
||||
Actuellement nous disposons d'un \texttt{RDing TEMPERHUM1V1.2}{} qui
|
||||
Actuellement nous disposons d'un capteur température et
|
||||
humidité, le
|
||||
\texttt{RDing} \texttt{TEMPERHUM1V1.2}{} qui
|
||||
semble un peu étrange à interpeller, et qui sera destiné à mesurer
|
||||
l'ambiance météo du DD2\footnote{Pas de mauvais esprit, merci...}.
|
||||
l'ambiance météo du Double Dragon\footnote{Pas de mauvais esprit, merci...},
|
||||
l'influence humaine n'étant pas à négliger en cas d'afflux du public..
|
||||
|
||||
Par la suite, nous pourrons récupérer (par liaison série ?) des données
|
||||
en provenance de l'automate de contrôle de l'enceinte. Notre dd2monitor
|
||||
Par la suite, nous pourrons récupérer
|
||||
(par liaison série, cf page \pageref{serial})
|
||||
des données diverses en provenance de l'automate de contrôle de l'enceinte.
|
||||
Cet automate\index{automate} est décrit page \pageref{automate}.
|
||||
|
||||
Le premier capteur de température sélectionné est le \textsc{LM35}\index{LM35}
|
||||
qui fournit en sortie une tension linéairement proportionnle à
|
||||
la température. Ils seront connectés sur l'automate qui s'en
|
||||
servira pour la régulation thermostatique.
|
||||
|
||||
Il nous reste à choisir d'autres capteurs pour d'autres métriques :
|
||||
humidité, lumière, vibrations, perturbations psychiques\dots
|
||||
|
||||
Notre dd2monitor
|
||||
devrait donc aussi être capable d'envoyer des alertes en cas de souci,
|
||||
par exemple si des algues\footnote{ou des pleurotes.} tentent de s'échapper.
|
||||
par exemple si des algues\footnote{Ou des pleurotes, ou des morilles...}
|
||||
tentent de s'échapper.
|
||||
|
||||
|
||||
\subsection{Stockage}
|
||||
|
||||
Pour entreposer toutes ces valeurs numériques, il existe plusieurs
|
||||
choix, et nous allons en évaluer quelques uns :
|
||||
\texttt{rrdb}\index{rrdb},
|
||||
\texttt{influxdb}\index{influxdb} (page \pageref{influxdb}),
|
||||
\texttt{gnocchi}\index{gnocchi}...
|
||||
choix, et nous allons en évaluer quelques uns~:
|
||||
|
||||
\texttt{flatfile}\index{flatfile} (page \pageref{flatfile}),
|
||||
\texttt{rrdb}\index{rrdb} (page \pageref{rrdb}),
|
||||
\texttt{influxdb}\index{Influxdb} (page \pageref{influxdb}),
|
||||
\texttt{gnocchi}\index{Gnocchi} (page \pageref{gnocchi})
|
||||
\texttt{Sqlite}\index{sqlite} (page \pageref{sqlite})
|
||||
|
||||
La représentation interne des valeurs reste à définir pour
|
||||
la plupart d'entre elles.
|
||||
|
||||
\subsection{Affichage}
|
||||
|
||||
Nous allons laisser un petit bac-à-sable pour Fred Fermion\index{nodejs},
|
||||
qui nous tartine les oreilles depuis trop longtemps avec son machinjs.
|
||||
qui nous tartine les oreilles depuis bien trop longtemps avec son machin.js.
|
||||
|
||||
Mais sachez déja que l'automate sera équipé d'un minitel, pourquoi ne
|
||||
pas en mettre un second sur le monitoring ?
|
||||
pas en mettre un second sur le monitoring ? Après tout, un peu
|
||||
d'eyecandy\index{eyecandy} ne peut pas faire de mal.
|
||||
C'est expliqué à la page \pageref{eyecandy}\index{curses}.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
% ===================================================================
|
||||
% nouveau 2019-02-22
|
||||
|
||||
\input{automate}
|
||||
|
||||
% ===================================================================
|
||||
|
||||
\section{Outils}
|
||||
|
||||
\subsection{Simulations}
|
||||
@ -90,63 +136,174 @@ phytotron pose un problème : d'où viennent les premières mesures ?
|
||||
C'est pour ça qu'il y a déja un générateur de \textit{fake-values} qui
|
||||
ne demande qu'à grandir.
|
||||
|
||||
Nous avons également un générateur de nombres divers et incohérents
|
||||
qui envoie des quadruplets d'entiers 10 bits précédés d'un caractere
|
||||
de bonne efficacité.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\subsection{Exemples}
|
||||
|
||||
Promis, on va en mettre !
|
||||
\textsf{Promis, on va en mettre ! Dès que ça marche\dots}
|
||||
|
||||
Un premier exemple avec rrdb en page \pageref{rrdb}.
|
||||
Le second cause des premiers essais du LM35\index{LM35},
|
||||
capteur de
|
||||
température analogique branché sur un Arduino Mega et relié
|
||||
par un port série (page \pageref{serialcode}).
|
||||
|
||||
Pour continuer dans une démarche disruptive, des outils
|
||||
avancés de visualisation sont proposés dans la rubrique
|
||||
\ref{eyecandy} qui parle de \texttt{vt100}\label{vt100}.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\subsection{Analyses}
|
||||
|
||||
Bla bla bla\dots Corrélations, toussa\dots
|
||||
\textsf{Bla bla bla\dots Corrélations, Gnuplot\index{gnuplot}, toussa\dots}
|
||||
|
||||
Peut-être demander à Schmod777 des références de
|
||||
documents bourbakistes ?
|
||||
documents bourbakistes ? J'ai entendu parler dans \textsc{irc}
|
||||
de choses étranges, comme ça :
|
||||
|
||||
\textsl{<schmod777> s/booz/booze pour la courbe qui majore les autres en moyenne serait
|
||||
d'une criante justesse scientifique ;)}
|
||||
|
||||
Ce qui donne quand même à réfléchir. À se demander quel savoir
|
||||
allons-nous pouvoir déduire de ces\footnote{non, c'est pas du bigdata.}
|
||||
chiffres improbables.
|
||||
(Re-)Découvrir les lois de l'inertie thermique ?
|
||||
Générer des formes d'ondes spatialisables ?
|
||||
Déplacer des petites \textit{bubulles} colorées ?
|
||||
Une histoire pour la section \pageref{detournements} ?
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{InfluxDB} \label{influxdb}
|
||||
\subsection{Archivage} \index{archivage} \label{archivage}
|
||||
|
||||
Au programme : écriture d'un injecteur en Perl\index{Perl}.
|
||||
\textsf{Conserver la mémoire de nos échecs.}
|
||||
|
||||
La création de cet outil de surveillance est un long parcours
|
||||
pavé d'essais et d'erreurs. Tout cela peut générer beaucoup
|
||||
de données. À titre d'exemple, la capture de température des
|
||||
premier essais sort environ 800 Ko par jour.
|
||||
99.99\% de ces chiffres sont inutiles, mais il peut arriver
|
||||
qu'on désire conserver l'historique d'une
|
||||
expérience réussie\footnote{En fait, c'est comme ça que la science existe}
|
||||
ou d'un
|
||||
\textit{epicfail\footnote{En fait, c'est comme ça que la science avance}}.
|
||||
|
||||
Nous devons donc rencontrer quelqu'un qui maitrise cette partie
|
||||
de la mouvance détournementale de l'espionnage.
|
||||
Je pense que Yaya\index{Yaya} pourra nous éclairer de ses lumières,
|
||||
si on lui demande gentiment.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Serial coms} \index{serial}
|
||||
\subsection{Affichage}\index{affichage}
|
||||
|
||||
Il va y avoir deux liaisons série entre l'automate et le monitoring.
|
||||
La première, que nous allons juste entrevoir, passera par le port
|
||||
USB de la carte Arduino. La seconde passera par un port série
|
||||
auxiliaire\footnote{Il y en a 4 sur le 2560} de celle-ci.
|
||||
Pour commencer presque simple, un exemple d'affichage avec
|
||||
Gnuplot\index{gnuplot} d'un fichier plat
|
||||
de température (décrit page \pageref{foo.dat}) :
|
||||
|
||||
\begin{verbatim}
|
||||
DATAFILE="foo.dat"
|
||||
IMAGE="graphe.png"
|
||||
|
||||
gnuplot << __EOC__
|
||||
set term png size 4200,640
|
||||
set output "${IMAGE}"
|
||||
set grid
|
||||
set title "Temperature dans le Double Dragon 2"
|
||||
set xdata time
|
||||
set timefmt "%s"
|
||||
set format x "%d, %H:%M:%S"
|
||||
set yrange [ 0.0 : 30.0]
|
||||
plot "${DATAFILE}" using 1:2 title " foo" with lines, \
|
||||
"${DATAFILE}" using 1:3 title " bar" with lines, \
|
||||
"${DATAFILE}" using 1:4 title "quux" with lines, \
|
||||
"${DATAFILE}" using 1:5 title "booz" with lines
|
||||
__EOC__
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
Prochainement, dès que le premier prototype matériel fournira des
|
||||
données, une tentative de visualisation animée sera faite avec
|
||||
POVray\index{POV}.
|
||||
|
||||
|
||||
% ===================================================================
|
||||
|
||||
\section{Configuration} \index{configuration} \label{configuration}
|
||||
|
||||
Pour adapter cet outil de surveillance aux variations du monde réel,
|
||||
nous devons nous-même lui décrire ce monde. Une description qui se
|
||||
fera avec des lignes de la forme '\texttt{input\_device s /dev/ttyACM0}'
|
||||
qui représentent des tuples
|
||||
\textit{clef-type-valeur}\footnote{Laissons les canards tranquilles.}
|
||||
de choses diverses.
|
||||
|
||||
La syntaxe n'est pas encore vraiment fixée, mais un fichier exemple est
|
||||
disponible pour des explication plus récentes, donc plus en
|
||||
rapport avec la réalité du code. En voici un extrait :
|
||||
|
||||
\begin{verbatim}
|
||||
# serial input from the control cpu
|
||||
input_device s /dev/ttyACM0
|
||||
input_speed i 9600
|
||||
# --------------------------------------------------
|
||||
# some values for the eyecandy displays
|
||||
eyecandy_banner s hacked by tTh
|
||||
\end{verbatim}
|
||||
|
||||
Certains de ces paramètres pourront être surchargé par des options
|
||||
de la ligne de commande\index{cli} ou des variables d'environnement.
|
||||
|
||||
% ===================================================================
|
||||
|
||||
\section{Flatfile} \label{flatfile}
|
||||
|
||||
Parfois, un fichier à plat est bien pratique, parce qu'il est facilement
|
||||
machinable avec des outils comme Awk\index{Awk}.
|
||||
Après tout, un \textsl{timestamp}\index{timestamp} et quelques valeurs
|
||||
numériques peuvent suffire à beaucoup de \textsl{usecases} de la
|
||||
vie courante.
|
||||
|
||||
Voici le premier exemple, un format\label{foo.dat} d'enregistrement de
|
||||
température facilement exploitable avec Awk ou Gnuplot :
|
||||
|
||||
\begin{verbatim}
|
||||
tth@phytotron:~/DD2-monitor/doc$ tail -3 ../serial/foo.dat
|
||||
1550673785 20.215054 20.107527 20.107527 20.215054
|
||||
1550673811 20.215054 20.215054 20.215054 20.215054
|
||||
1550673836 20.215054 20.107527 20.215054 20.215054
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Détournements}
|
||||
|
||||
Dans le contexte myryssien, il est évident que l'aspect artistique
|
||||
doit être dès le départ pris en compte.
|
||||
Les possibilités ne seront limitées que par votre manque d'imagination.
|
||||
|
||||
Mais si vous voulez un petit exemple, imaginez des courbes de température
|
||||
qui pilotent un \texttt{uGen} de Chuck\index{chuck} ou des algues dont la lumière
|
||||
envoie du \texttt{cv/gate} en temps réel...
|
||||
|
||||
|
||||
\input{storages}
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Conclusion}\label{conclusion}\index{conclusion}
|
||||
\input{serial}
|
||||
\input{detournements}
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Conclusion} \label{conclusion} \index{conclusion}
|
||||
|
||||
En fait, tout reste à faire. Mais ça peut être un beau projet
|
||||
aux implications et usages multiples.
|
||||
aux implications et usages multiples. À condition de bien
|
||||
faire les choses.
|
||||
|
||||
Un couteau suisse de la capture du monde réel, un point pivot
|
||||
de nos diverses interprétations de
|
||||
l'univers\footnote{non, la terre n'est pas plate} et des interactions
|
||||
étranges entre des paramètres sans relation clairement definie.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\setlength{\parskip}{0.05cm plus 0.05cm}
|
||||
|
||||
\pagebreak \tableofcontents
|
||||
% \pagebreak \tableofcontents
|
||||
|
||||
\printindex
|
||||
|
||||
|
29
doc/detournements.tex
Normal file
29
doc/detournements.tex
Normal file
@ -0,0 +1,29 @@
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Détournements} \label{detournements}
|
||||
|
||||
Dans le contexte myryssien\index{Myrys}, il est évident que l'aspect
|
||||
artistique\index{Art}
|
||||
doit être dès le départ pris en compte.
|
||||
Les possibilités ne seront limitées que par votre manque d'imagination.
|
||||
|
||||
Si vous voulez un petit exemple, imaginez des courbes de température
|
||||
qui pilotent un \texttt{uGen} de Chuck\index{Chuck} ou des algues dont
|
||||
les pulses lumineux envoie du \texttt{cv/gate} en temps réel.
|
||||
|
||||
\subsection{Variante sonore}
|
||||
|
||||
Un peu de \texttt{awk} pipé dans du \texttt{sox} ?
|
||||
Voire même l'occasion (ou un bon prétexte) de résoudre ce problème
|
||||
de saut de phase qui me tracasse depuis des mois ?
|
||||
|
||||
\subsection{Eye candy}\index{eyecandy}\label{eyecandy}
|
||||
|
||||
Pour maximiser l'impact visuel, il sera convenant de sortir du
|
||||
cadre pseudo-moderne des omniprésents écrans de ces
|
||||
smartphones\footnote{Quand les téléphones étaient attachés par
|
||||
un fil, les humains étaient libres.} qui nous lavent le cerveau.
|
||||
Sortons donc du contexte pixeliste et revenons aux fondamentaux :
|
||||
le caractère\index{ncurses} blanc sur fond noir,
|
||||
avec toute la simplicité de son concept sémantique.
|
||||
|
8
doc/mkdoc.sh
Executable file
8
doc/mkdoc.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
pdflatex dd2-monitoring.tex
|
||||
|
||||
makeindex dd2-monitoring
|
||||
|
||||
pdflatex dd2-monitoring.tex
|
59
doc/serial.tex
Normal file
59
doc/serial.tex
Normal file
@ -0,0 +1,59 @@
|
||||
% ===================================================================
|
||||
|
||||
\section{Serial coms} \index{serial} \label{serial}
|
||||
|
||||
Il va y avoir deux liaisons série entre l'automate et le monitoring.
|
||||
La première, que nous allons juste entrevoir, passera par le port
|
||||
USB de la carte Arduino. La seconde passera par un port série
|
||||
auxiliaire\footnote{Il y en a 4 sur le mega 2560} de celle-ci.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Un gros souci}
|
||||
|
||||
\begin{lstlisting}
|
||||
tcgetattr(uart0, &options);
|
||||
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
|
||||
options.c_iflag = IGNPAR;
|
||||
options.c_oflag = 0;
|
||||
options.c_lflag = 0;
|
||||
tcflush(uart0, TCIFLUSH);
|
||||
tcsetattr(uart0, TCSANOW, &options);
|
||||
\end{lstlisting}
|
||||
|
||||
Et en fait, le \texttt{read} sur le \textsl{fd} du serial device
|
||||
n'est pas bloquant, \texttt{perror} annonce \emph{success}, mais
|
||||
rien ne marche. L'année 2019 va commencer sur du vaudou programming%
|
||||
\footnote {aka shotgun debugging.}.
|
||||
|
||||
\textit{29 décembre 2018} : le petit grain de magie\index{magie}
|
||||
est très simple à mettre en oeuvre, mais
|
||||
très difficle à spotter dans le gazillion d'options. Il semblerait
|
||||
que mettre \texttt{options.c\_cc[VMIN]} à 1 permet d'avancer vers
|
||||
l'étape suivante.
|
||||
|
||||
Laquelle étape est une tentative d'utilisation de \texttt{select(2)},
|
||||
dans l'objectif de pouvoir gérer nous-même le \textit{timeout},
|
||||
laquelle tentative n'est pas du tout concluante.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Protocole} \index{protocole} \label{serialprotocol}
|
||||
|
||||
L'automate va avoir plusieurs types de données à envoyer.
|
||||
Nous allons donc transférer ces valeurs sous forme de ligne
|
||||
de texte commençant par un caractère clef
|
||||
(par exemple \texttt{T} pour les températures)
|
||||
et se terminant par un \textit{newline}.
|
||||
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\subsection{Un peu de code} \label{serialcode}
|
||||
|
||||
\begin{lstlisting}
|
||||
main()
|
||||
{
|
||||
while(fork());
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ===================================================================
|
111
doc/storages.tex
Normal file
111
doc/storages.tex
Normal file
@ -0,0 +1,111 @@
|
||||
% ============================================
|
||||
%
|
||||
% Various storages systems
|
||||
%
|
||||
% ============================================
|
||||
|
||||
\section{RRDB} \label{rrdb}
|
||||
|
||||
Première tentative d'utilisation le lendemain du premier apéro 2019
|
||||
du Tetalab\footnote{Jean-Yves, je vous demande de vous calmer !}.
|
||||
|
||||
Je suis parti sur quelques scripts shell, pour créer, mettre à jour et
|
||||
analyser les enregistrements d'une valeur de type \textsc{gauge}.
|
||||
|
||||
\subsection{Create}
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
starttime=$(date +'%s')
|
||||
echo creating $RRDB at ${starttime}s since epoch
|
||||
rrdtool create $RRDB \
|
||||
--start $starttime \
|
||||
--step 60 \
|
||||
DS:value:GAUGE:150:0:10 \
|
||||
RRA:AVERAGE:0.5:1:60
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Update} \index{rrdtool}
|
||||
|
||||
Une fois la base créée, il faut bien la remplir.
|
||||
Dans cet exemple, nous allons utiliser le \textit{load}
|
||||
de notre Linux.
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
ctime=$(date +'%s')
|
||||
value=$(cut -d ' ' -f 1 /proc/loadavg)
|
||||
|
||||
# inject value in the rrdb file
|
||||
rrdtool update $RRDB ${ctime}:${value}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Analyze}
|
||||
|
||||
Nous allons essayer d'exploiter les données dûrement acquises
|
||||
pendant les heures qui précèdent\dots
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
tmpf="somevalues.dat"
|
||||
rrdtool fetch $RRDB LAST |
|
||||
tr -d ':' |
|
||||
awk '
|
||||
(!/nan/ && NF==2) { print $1, $2 }
|
||||
' \
|
||||
> ${tmpf}
|
||||
|
||||
# as an example, we are gnuploting our datas
|
||||
gnuplot << __EOC__
|
||||
set term png size 800,600
|
||||
set output "graphe.png"
|
||||
set grid
|
||||
plot "${tmpf}" with lines
|
||||
__EOC__
|
||||
|
||||
rm ${tmpf}
|
||||
\end{lstlisting}
|
||||
|
||||
Il semble bien que l'utilisation de \texttt{fetch} ne soit pas
|
||||
vraiment prévue pour ça, donc j'en arrive à la conclusion que
|
||||
quelque chose m'échappe.
|
||||
|
||||
On va laisser ça en suspens pour le moment.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{InfluxDB} \label{influxdb}
|
||||
|
||||
La communication avec la bédédé se fait \textit{over HTTP}, un peu
|
||||
comme tous ces trucs de d'jeunz d'aujourd'hui\dots
|
||||
|
||||
Au programme : écriture d'un injecteur en Perl\index{Perl}, en suivant
|
||||
plus ou moins l'exemple de rrdb..
|
||||
|
||||
Ceci dit, en Debian stable, on n'a que la version 1.0, qui ne
|
||||
correspond plus trop à l'actualité. Et la \textit{current} semble
|
||||
trop fatiguante à compiler pour ce soir, ni même pour ce week-end.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
\section{Gnocchi} \label{gnocchi} \index{Gnocchi}
|
||||
|
||||
\texttt{pip install gnocchi[postgresql,ceph,keystone]}, finalement,
|
||||
çe ne me donne pas trop envie. C'est du genre \textit{usinagaz}.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
\section{Sqlite} \index{sqlite} \label{sqlite}
|
||||
|
||||
\textsf{À regarder de près}
|
||||
|
||||
Est-il possible de traiter des \textit{time series} en SQL\index{SQL} ?
|
||||
Peut-on utiliser Sqlite depuis un programme en Perl\index{Perl} ?
|
||||
Faut-il commencer à trouver un \textit{usecase} crédible ?
|
||||
NodeJs\index{nodejs} peut-il lire du Sqlite ?
|
||||
|
92
essai.c
92
essai.c
@ -2,35 +2,101 @@
|
||||
* essai.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curses.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "funcs.h"
|
||||
#include "core/utils.h"
|
||||
#include "core/sysmetrics.h"
|
||||
#include "serial/serial.h"
|
||||
#include "viz/curses/ecran.h"
|
||||
|
||||
int verbosity;
|
||||
int verbosity;
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
int affiche_valeurs(int sfd, int nbloops)
|
||||
{
|
||||
int idx, foo;
|
||||
char ligne[200], buff[200];
|
||||
float datas[4];
|
||||
|
||||
for (idx=0; idx<nbloops; idx++) {
|
||||
|
||||
foo = getline_to(sfd, ligne, 100, 0);
|
||||
#if DEBUG_LEVEL
|
||||
if (foo) fprintf(stderr, "get values -> %d\n", foo);
|
||||
#endif
|
||||
|
||||
foo = parse4values(ligne, 'T', datas);
|
||||
#if DEBUG_LEVEL
|
||||
if (foo) fprintf(stderr, "parse -> %d\n", foo);
|
||||
#endif
|
||||
|
||||
values2temperature(datas);
|
||||
|
||||
foo = aff7segs_float(stdscr, 3, 5, datas[0]);
|
||||
foo = aff7segs_float(stdscr, 14, 5, datas[1]);
|
||||
foo = aff7segs_float(stdscr, 25, 5, datas[2]);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* --------------------------------------------------------------- */
|
||||
static void finish(int signal)
|
||||
{
|
||||
endwin();
|
||||
fprintf(stderr, "end of pid %d\n", getpid());
|
||||
exit(0);
|
||||
}
|
||||
/* --------------------------------------------------------------- */
|
||||
void help(int k)
|
||||
{
|
||||
puts("options : ");
|
||||
puts("\t-d\tserial device to read.");
|
||||
puts("\t-v\tincrease verbosity.");
|
||||
exit(0);
|
||||
}
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, foo;
|
||||
int type = 0;
|
||||
double loads[3];
|
||||
int serial_in;
|
||||
char *device = "/dev/ttyACM0";
|
||||
|
||||
while ((opt = getopt(argc, argv, "vst:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "d:hv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd': device = optarg; break;
|
||||
case 'h': help(0); break;
|
||||
case 'v': verbosity++; break;
|
||||
case 's': srand(getpid()); break;
|
||||
case 't': type = atoi(optarg); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
foo = get_loadavg(loads);
|
||||
if (foo) fprintf(stderr, "get loadavg -> %d\n", foo);
|
||||
|
||||
printf("%f %f %f %f\n", dtime(), loads[0], loads[1], loads[2]);
|
||||
serial_in = prepare_UART(device, 9600);
|
||||
if (serial_in < 0) {
|
||||
fprintf(stderr, "%s : open device : error %d on %s\n",
|
||||
argv[0], serial_in, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
initscr();
|
||||
nonl(); cbreak(); noecho();
|
||||
keypad(stdscr, TRUE); /* acces aux touches 'curseur' */
|
||||
fond_ecran(" Demonstrator ");
|
||||
|
||||
affiche_valeurs(serial_in, 10000);
|
||||
|
||||
/*
|
||||
* plop, on a fini, il faut restaurer la console
|
||||
*/
|
||||
finish(0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
15
exemple.sh
15
exemple.sh
@ -6,21 +6,28 @@ DATAFILE=/tmp/fake-datafile
|
||||
> ${DATAFILE}
|
||||
for s in $(seq 1 1000)
|
||||
do
|
||||
v=$(./fake-values -s -t 1 2> /dev/null)
|
||||
v=$(./fake-values -s -t 4)
|
||||
echo $s $v >> ${DATAFILE}
|
||||
done
|
||||
|
||||
tail -5 ${DATAFILE}
|
||||
|
||||
#----- do dome useless computations
|
||||
awk '
|
||||
NR==1 { debut = $2 }
|
||||
NR==1 {
|
||||
debut = $2
|
||||
}
|
||||
|
||||
{
|
||||
# print $2-debut, $3
|
||||
v = int($3/25);
|
||||
v = int($3/35);
|
||||
bucket[v]++;
|
||||
}
|
||||
|
||||
END {
|
||||
for (v=0; v<40; v++) {
|
||||
for (foo=0; foo<bucket[v]; foo++) {
|
||||
printf "%4d ", v;
|
||||
for (foo=0; foo<bucket[v]/2; foo++) {
|
||||
printf "-";
|
||||
}
|
||||
print "*"
|
||||
|
@ -1,12 +1,14 @@
|
||||
/*
|
||||
* fake-values.c
|
||||
* -------------
|
||||
* useless software
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "funcs.h"
|
||||
#include "core/utils.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
@ -30,7 +32,7 @@ if (verbosity > 1) {
|
||||
fprintf(stderr, "fake values - %s %s\n", __DATE__, __TIME__);
|
||||
}
|
||||
|
||||
printf("%f %d\n", dtime(), random1000(type));
|
||||
printf("%.3f %4d\n", dtime(), random1000(type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
13
funcs.h
13
funcs.h
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* funcs.c
|
||||
*/
|
||||
|
||||
/* return an in random value in [0.999] */
|
||||
int random1000(int mode);
|
||||
|
||||
/* get the 'timeofday' as a double float */
|
||||
double dtime(void);
|
||||
|
||||
/* only usable on standard Linux ! */
|
||||
int get_loadavg(double where[]);
|
||||
|
@ -1,11 +1,22 @@
|
||||
## Gnocchi
|
||||
# Gnocchi
|
||||
|
||||
# blabla commercial
|
||||
## blabla commercial
|
||||
|
||||
<<<<<<< HEAD
|
||||
|
||||
|
||||
_The problem that [Gnocchi](https://gnocchi.xyz/) solves is the storage and indexing of
|
||||
time series data and resources at a large scale.
|
||||
=======
|
||||
_The problem that [Gnocchi](https://gnocchi.xyz/) solves is the storage and
|
||||
indexing of time series data and resources at a large scale.
|
||||
>>>>>>> b47e467d21cec6ee688b4407d3ec54fa33e67ba6
|
||||
This is useful in modern cloud platforms which are not only huge
|
||||
but also are dynamic and potentially multi-tenant.
|
||||
Gnocchi takes all of that into account._
|
||||
|
||||
Bref, il faut essayer ce truc. Un de ces jours...
|
||||
|
||||
`pip install gnocchi[postgresql,ceph,keystone]`
|
||||
bon, on va peut-être attendre :)
|
||||
|
||||
|
@ -12,7 +12,10 @@ purpose-built platform that InfluxData provides._
|
||||
|
||||
# On essaye ?
|
||||
|
||||
Ok, c'est parti. On va écrire un injecteur en Perl. Puis enchainer sur
|
||||
Ok, c'est parti. Premier souci, la documentation est assez légère.
|
||||
|
||||
|
||||
On va tenter d'écrire un injecteur en Perl. Puis enchainer sur
|
||||
une visualisation dynamique des données en lancer de rayon.
|
||||
Projet ambitieux ? Non, la suite sera bien pire.
|
||||
|
||||
|
13
influxdb/create.sh
Executable file
13
influxdb/create.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# create an inflix databasse
|
||||
#
|
||||
|
||||
influx -host localhost -port 8086 << __EOC__
|
||||
|
||||
settings
|
||||
CREATE DATABASE tests
|
||||
__EOC__
|
||||
|
||||
lynx -head -dump http://localhost:8086/ping?verbose=true
|
@ -2,6 +2,9 @@
|
||||
|
||||
use strict;
|
||||
|
||||
my $host = "localhost";
|
||||
my $port = 8086;
|
||||
|
||||
print "injecteur v 0\n";
|
||||
|
||||
0;
|
||||
|
@ -1,3 +1,39 @@
|
||||
<<<<<<< HEAD
|
||||
## Round Robin Database
|
||||
=======
|
||||
# Round Robin Database
|
||||
|
||||
Un grand classique du genre. Délicat à comprendre au début.
|
||||
Les principes sous-jacents sont assez pointus, et leur mise en oeuvre
|
||||
loin d'être évidente pour les newbies.
|
||||
|
||||
La lecture de la manpage `rrdtutorial` est indispensable.
|
||||
|
||||
https://oss.oetiker.ch/rrdtool/tut/rrd-beginners.en.html
|
||||
|
||||
## premier exemple
|
||||
|
||||
Un petit peu de code fabriqué à la rache.
|
||||
|
||||
- `create.sh`
|
||||
- `update.sh`
|
||||
- `getvalues.sh`
|
||||
- `mkgraph.sh`
|
||||
|
||||
Suffisant pour comprendre le principe général, mais très flou
|
||||
sur les détails.
|
||||
|
||||
## et après ?
|
||||
|
||||
Trouver une interface en C pour faciliter la vie des gens.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
>>>>>>> b47e467d21cec6ee688b4407d3ec54fa33e67ba6
|
||||
|
||||
Un grand classique du genre.
|
||||
|
6
rrdb/commun.sh
Normal file
6
rrdb/commun.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# commun definitions for rrdb tests
|
||||
#
|
||||
|
||||
export RRDB=$HOME/TMP/tests.rrd
|
||||
|
21
rrdb/create.sh
Executable file
21
rrdb/create.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# creating the test database
|
||||
#
|
||||
|
||||
source ./commun.sh
|
||||
|
||||
starttime=$(date +'%s')
|
||||
|
||||
echo creating $RRDB at ${starttime}s since epoch
|
||||
|
||||
rrdtool create $RRDB \
|
||||
--start $starttime \
|
||||
--step 60 \
|
||||
DS:value:GAUGE:150:0:10 \
|
||||
RRA:AVERAGE:0.5:1:60
|
||||
|
||||
|
||||
|
||||
|
29
rrdb/getvalues.sh
Executable file
29
rrdb/getvalues.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
|
||||
tmpf="somevalues.dat"
|
||||
|
||||
rrdtool fetch $RRDB LAST \
|
||||
--start 0 |
|
||||
tr -d ':' |
|
||||
awk '
|
||||
(!/nan/ && NF==2) { print $1, $2 }
|
||||
' \
|
||||
> ${tmpf}
|
||||
|
||||
#
|
||||
# as an example, we are gnuploting our datas
|
||||
#
|
||||
gnuplot << __EOC__
|
||||
set term png size 1024,512
|
||||
set output "graphe.png"
|
||||
set grid
|
||||
set xdata time
|
||||
set timefmt "%s"
|
||||
set format x "%m/%d\n%H:%M"
|
||||
plot "${tmpf}" using 1:2 with lines
|
||||
__EOC__
|
||||
|
||||
# rm ${tmpf}
|
||||
|
14
rrdb/insert.sh
Executable file
14
rrdb/insert.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
|
||||
ctime=$(date +'%s')
|
||||
value=$(cut -d ' ' -f 1 /proc/loadavg)
|
||||
|
||||
# display and write value to a file
|
||||
echo ${ctime} ${value} | tee -a bar.dat
|
||||
|
||||
# inject value in the rrdb file
|
||||
rrdtool update $RRDB ${ctime}:${value}
|
||||
|
||||
|
11
rrdb/mkgraph.sh
Executable file
11
rrdb/mkgraph.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
source ./commun.sh
|
||||
|
||||
rrdtool graph value.png \
|
||||
--start 0 --end now \
|
||||
-w 800 -h 600 \
|
||||
DEF:value=${RRDB}:value:LAST \
|
||||
LINE1:value#0000FF
|
||||
|
||||
|
@ -1,9 +1,16 @@
|
||||
|
||||
OPT = -Wall -DDEBUG_LEVEL=1
|
||||
OPT = -Wall -DDEBUG_LEVEL=0
|
||||
OBJS = serial.o funcs.o
|
||||
# ---------------------------------------------------
|
||||
|
||||
serial.o: serial.c serial.h Makefile
|
||||
gcc ${OPT} -c $<
|
||||
|
||||
t: t.c serial.o Makefile
|
||||
gcc ${OPT} $< serial.o -o $@
|
||||
funcs.o: funcs.c serial.h Makefile
|
||||
gcc ${OPT} -c $<
|
||||
|
||||
# ---------------------------------------------------
|
||||
|
||||
t: t.c Makefile ${OBJS}
|
||||
gcc ${OPT} $< ${OBJS} -o $@
|
||||
|
||||
|
@ -1,14 +1,45 @@
|
||||
|
||||
# Serial Input
|
||||
|
||||
But premier de ce module : recevoir les données fournies par l'automate
|
||||
de contrôle du phytotron.
|
||||
|
||||
Ayant déja pratiqué ce genre de chose pour un déja ancien
|
||||
[projet](http://art.dinorama.fr/bdf/)
|
||||
Ayant déja pratiqué ce genre de chose (recevoir des données par rs232)
|
||||
pour un déja ancien
|
||||
[projet artsitique](http://art.dinorama.fr/bdf/) conçu par et
|
||||
avec _MadPhoenix_, je me propose de reprendre quelques parties de ce code,
|
||||
de le remettre au gout du jour et de le tester dès que possible.
|
||||
|
||||
## principe général
|
||||
|
||||
Pour écouter plusieurs lignes simultanément, chaque port sera traité
|
||||
par un _thread_ séparé, et les diverses données reçues seront pré-traitées
|
||||
par celui-ci. Les flux de données seront alors agrégées par
|
||||
le célèbre *synthétiseur d'évènement* mis au point il y a très longtemps
|
||||
par le professeur Cispeo.
|
||||
|
||||
## À venir...
|
||||
|
||||
Un petit exemple ?
|
||||
|
||||
Oui, voilà. À ce jour (20 déc. 2018), on va dire que ça ne marche pas.
|
||||
Il faut dire que les `serial devices` ont toujours étés un peu le
|
||||
domaine de la magie noire. Mais quand même, coincer sur un `read` qui
|
||||
ne bloque pas, c'est un peu ironique.
|
||||
|
||||
Après un peu plus d'investigation, j'en arrive à conclure qu'il y a
|
||||
plein de subtilités entre les diverses variantes d'Arduino. Mais pas que.
|
||||
Je pense que les quatre ports série supplémentaires de l'Arduino Mega
|
||||
seront moins capricieux.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
29
serial/essai.sh
Executable file
29
serial/essai.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEVICE="/dev/ttyACM0"
|
||||
DATAFILE="foo.dat"
|
||||
TMPFILE="/tmp/dd2data"
|
||||
|
||||
IMAGE="graphe.png"
|
||||
NB_READ=10
|
||||
|
||||
./t -n ${NB_READ} -d ${DEVICE} | tee -a ${DATAFILE}
|
||||
|
||||
gnuplot << __EOC__
|
||||
set term png size 1600,640
|
||||
set output "${IMAGE}"
|
||||
set grid
|
||||
set title "Temperature dans le Double Dragon 2"
|
||||
set xdata time
|
||||
set timefmt "%s"
|
||||
set format x "%d, %H:%M"
|
||||
set yrange [ 0.0 : 30.0 ]
|
||||
plot "${DATAFILE}" using 1:2 title " foo" with lines, \
|
||||
"${DATAFILE}" using 1:3 title " bar" with lines, \
|
||||
"${DATAFILE}" using 1:4 title "quux" with lines, \
|
||||
"${DATAFILE}" using 1:5 title "booz" with lines
|
||||
__EOC__
|
||||
|
||||
# display ${IMAGE}
|
||||
|
||||
|
88
serial/funcs.c
Normal file
88
serial/funcs.c
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/*
|
||||
* compute the integer mean value of a four values
|
||||
* tagged lines.
|
||||
*/
|
||||
int parseXvalue(char *line, char cflag)
|
||||
{
|
||||
int value, foo;
|
||||
int vrd[4];
|
||||
|
||||
value=0;
|
||||
|
||||
if ( cflag != *line ) {
|
||||
if (verbosity) {
|
||||
fprintf(stderr, "%s : line[0] 0x%x bad\n",
|
||||
__func__, *line);
|
||||
}
|
||||
return -777;
|
||||
}
|
||||
|
||||
foo = sscanf(line+1, "%d %d %d %d", vrd, vrd+1, vrd+2, vrd+3);
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "%s : sscanf -> %d\n", __func__, foo);
|
||||
#endif
|
||||
if (4 != foo) {
|
||||
return -666;
|
||||
}
|
||||
for (foo=0; foo<4; foo++) {
|
||||
value += vrd[foo];
|
||||
}
|
||||
|
||||
value /= 4;
|
||||
|
||||
return value;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
/*
|
||||
* this fonction is specific to the LM35 thermo-sensor
|
||||
* connected to a ADC pin of an Arduino Mega
|
||||
*
|
||||
* WARNING !
|
||||
* this function _must_ be modofied if you change the
|
||||
* Vref of the Analog to Digital converter on the
|
||||
* Arduino !
|
||||
*
|
||||
*/
|
||||
int values2temperature(float array[4])
|
||||
{
|
||||
int foo;
|
||||
for (foo=0; foo<4; foo++) {
|
||||
array[foo] *= (1.1 / 1023.0 * 100.0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int parse4values(char *line, char cflag, float array[4])
|
||||
{
|
||||
float ftmp[4];
|
||||
int foo;
|
||||
|
||||
if ( cflag != *line ) {
|
||||
if (verbosity) {
|
||||
fprintf(stderr, "%s : line[0] 0x%x bad\n",
|
||||
__func__, *line);
|
||||
}
|
||||
return -777;
|
||||
}
|
||||
|
||||
foo = sscanf(line+1, "%f %f %f %f", ftmp, ftmp+1, ftmp+2, ftmp+3);
|
||||
if (4 != foo) {
|
||||
fprintf(stderr, "%s : sscanf -> %d\n", __func__, foo);
|
||||
return -666;
|
||||
}
|
||||
// fprintf(stderr, "\tV %f\n", ftmp[0]);
|
||||
|
||||
memcpy(array, ftmp, 4*sizeof(float));
|
||||
|
||||
return 4;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
105
serial/serial.c
105
serial/serial.c
@ -1,7 +1,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> //Used for UART
|
||||
#include <fcntl.h> //Used for UART
|
||||
#include <termios.h> //Used for UART
|
||||
@ -39,7 +41,7 @@ int baudbits;
|
||||
struct termios options;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "%s ( %s %d )\n", __func__, port, baudrate);
|
||||
fprintf(stderr, ">>> %s ( %s %d )\n", __func__, port, baudrate);
|
||||
#endif
|
||||
// OPEN THE UART
|
||||
// The flags (defined in fcntl.h):
|
||||
@ -60,8 +62,8 @@ fprintf(stderr, "%s ( %s %d )\n", __func__, port, baudrate);
|
||||
// shall not cause the terminal device to become the controlling terminal
|
||||
// for the process.
|
||||
|
||||
uart0 = open(port, O_RDWR | O_NOCTTY);
|
||||
if (uart0== -1)
|
||||
uart0 = open(port, O_RDONLY | O_NOCTTY);
|
||||
if (uart0 < 0)
|
||||
{
|
||||
perror("unable to open uart ");
|
||||
return -1;
|
||||
@ -84,32 +86,44 @@ if (uart0== -1)
|
||||
|
||||
|
||||
baudbits = baudrate2const(baudrate);
|
||||
#if DEBUG_LEVEL
|
||||
#if DEBUG_LEVEL > 1
|
||||
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
|
||||
#endif
|
||||
|
||||
memset(&options, 0, sizeof(options));
|
||||
|
||||
tcgetattr(uart0, &options);
|
||||
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD; //<Set baud rate
|
||||
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
|
||||
options.c_iflag = IGNPAR;
|
||||
options.c_oflag = 0;
|
||||
options.c_lflag = 0;
|
||||
|
||||
options.c_cc[VMIN] = 1; /* ask for blocking read */
|
||||
|
||||
tcflush(uart0, TCIFLUSH);
|
||||
tcsetattr(uart0, TCSANOW, &options);
|
||||
|
||||
tcflush(uart0, TCIFLUSH); /* do it again, sam */
|
||||
|
||||
return uart0;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/*
|
||||
* this function have NO timeout !
|
||||
* blocking read is not blocking, wtf ?
|
||||
*/
|
||||
int getbyte(int fd)
|
||||
{
|
||||
unsigned char byte;
|
||||
int foo;
|
||||
|
||||
byte = 0;
|
||||
|
||||
foo = read(fd, &byte, 1);
|
||||
if (1 != foo)
|
||||
{
|
||||
perror("read a byte");
|
||||
fprintf(stderr, "byte %d rd %d errno %d\n",
|
||||
byte, foo, errno);
|
||||
return -1;
|
||||
}
|
||||
return (int)byte;
|
||||
@ -124,11 +138,10 @@ struct timeval timeout;
|
||||
fd_set rfds;
|
||||
int retval;
|
||||
|
||||
timeout.tv_sec = to_ms / 1000;
|
||||
timeout.tv_sec = to_ms / 1000;
|
||||
timeout.tv_usec = (to_ms % 1000) * 1000;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "timeout %6d is %4ld %6ld\n", to_ms,
|
||||
#if DEBUG_LEVEL > 1
|
||||
fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
|
||||
timeout.tv_sec, timeout.tv_usec);
|
||||
#endif
|
||||
|
||||
@ -136,37 +149,91 @@ FD_ZERO (&rfds);
|
||||
FD_SET (fd, &rfds);
|
||||
|
||||
retval = select(1, &rfds, NULL, NULL, &timeout);
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "%s : select -> %d\n", __func__, retval);
|
||||
fprintf(stderr, "%s : select on fd %d -> %d\n", __func__, fd, retval);
|
||||
#endif
|
||||
|
||||
retval = retval < 0 ? -1 : retval;
|
||||
|
||||
switch (retval) {
|
||||
|
||||
case -1:
|
||||
fprintf(stderr, "omg ?\n");
|
||||
byte = -1;
|
||||
retval = -1;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
fprintf(stderr, "timeout\n");
|
||||
byte = -99;
|
||||
fprintf(stderr, "timeout %ld.%ld\n",
|
||||
timeout.tv_sec, timeout.tv_usec);
|
||||
retval = -99;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s default -> %d\n", __func__, retval);
|
||||
if (retval==fd) {
|
||||
read(fd, &byte, 1);
|
||||
fprintf(stderr, "got 0x%02x\n", byte);
|
||||
retval = byte;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%d bad fd ?\n", retval);
|
||||
byte = -3;
|
||||
retval = -3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return byte;
|
||||
return retval;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* timeout is in milliseconds */
|
||||
|
||||
int getline_to(int fd, char *where, int szm, int to_ms)
|
||||
{
|
||||
int curpos, byte, retval;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, ">>> %s ( %d %p %d %d )\n", __func__,
|
||||
fd, where, szm, to_ms);
|
||||
#endif
|
||||
|
||||
curpos = 0;
|
||||
retval = -7; /* magic number powa */
|
||||
where[0] = '\0'; /* erase all the bs */
|
||||
|
||||
for(;;) {
|
||||
if (to_ms) {
|
||||
byte = getbyte_to (fd, to_ms);
|
||||
}
|
||||
else {
|
||||
byte = getbyte(fd);
|
||||
}
|
||||
|
||||
if (byte < 0) {
|
||||
fprintf(stderr, "%s : something is wrong %d\n",
|
||||
__func__, byte);
|
||||
retval = byte;
|
||||
break;
|
||||
}
|
||||
|
||||
if ('\n' == byte) { /* got an EOL ? */
|
||||
where[curpos] = '\0';
|
||||
retval = curpos;
|
||||
break;
|
||||
}
|
||||
|
||||
if (curpos < szm) { /* ya de la place */
|
||||
where[curpos] = byte;
|
||||
curpos++;
|
||||
}
|
||||
else { /* oups overflow */
|
||||
retval = -6;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, "%s -> '%s'\n", __func__, where);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
|
@ -6,10 +6,19 @@
|
||||
|
||||
int prepare_UART(char *port, int bauds);
|
||||
|
||||
int getbyte(int fd);
|
||||
int getbyte(int fd); /* really brotched func */
|
||||
|
||||
|
||||
/* timeout is exprimed in milliseconds. */
|
||||
int getbyte_to (int fd, int to_ms);
|
||||
|
||||
int getline_to(int fd, char *where, int szm, int to_ms);
|
||||
|
||||
/* auxiliary and test functions */
|
||||
|
||||
int parseXvalue(char *asciidatas, char id);
|
||||
int values2temperature(float array[4]);
|
||||
|
||||
int parse4values(char *line, char cflag, float array[4]);
|
||||
|
||||
|
||||
|
113
serial/t.c
113
serial/t.c
@ -1,29 +1,114 @@
|
||||
|
||||
/*
|
||||
* Experiments with the serial input
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h> //Used for UART
|
||||
#include <fcntl.h> //Used for UART
|
||||
#include <errno.h>
|
||||
#include <termios.h> //Used for UART
|
||||
#include <getopt.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int loop(int sfd, int iters)
|
||||
{
|
||||
int count, foo;
|
||||
long temps;
|
||||
char ligne[200], buff[200];
|
||||
float datas[4];
|
||||
struct tm *p_tms;
|
||||
|
||||
for (count=0; count<iters; count++) {
|
||||
foo = getline_to(sfd, ligne, 100, 0);
|
||||
//
|
||||
if (verbosity) {
|
||||
/* fprintf(stderr, "getline #%d on %d -> %d\n",
|
||||
count, iters, foo); */
|
||||
fprintf(stderr, "%s\n", ligne);
|
||||
}
|
||||
//
|
||||
if (verbosity > 1)
|
||||
{
|
||||
p_tms = localtime(&temps);
|
||||
(void)strftime(buff, 19, "%H:%M:%S", p_tms);
|
||||
fprintf(stderr, "%s %6d / %d\n", buff, count, iters);
|
||||
}
|
||||
//
|
||||
foo = parse4values(ligne, 'T', datas);
|
||||
//
|
||||
if (foo >= 0) {
|
||||
temps = time(NULL);
|
||||
values2temperature(datas);
|
||||
printf("%ld %f %f %f %f\n", temps,
|
||||
datas[0], datas[1], datas[2], datas[3]);
|
||||
fflush(stdout);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: parse -> %d\n", __func__, foo);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
void help(int k)
|
||||
{
|
||||
puts("options : ");
|
||||
puts("\t-d\tserial device to read.");
|
||||
puts("\t-n\tnumber of records to grab.");
|
||||
puts("\t-v\tincrease verbosity.");
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int serial_in;
|
||||
int byte, foo, to;
|
||||
int serial_in;
|
||||
char *device = "/dev/ttyACM0";
|
||||
int nbre, speed, opt;
|
||||
|
||||
serial_in = prepare_UART("/dev/ttyS0", 9600);
|
||||
fprintf(stderr, "prepare uart -> %d\n", serial_in);
|
||||
/* set some default values */
|
||||
verbosity = 0;
|
||||
nbre = 25;
|
||||
speed = 9600;
|
||||
|
||||
for (foo=0; foo<20; foo++) {
|
||||
to = (foo+1) * 666;
|
||||
byte = getbyte_to(serial_in, to);
|
||||
if (byte < 0) {
|
||||
fprintf(stderr, "get byte : err is %d\n", byte);
|
||||
while ((opt = getopt(argc, argv, "d:n:vh")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v': verbosity++; break;
|
||||
case 'n': nbre = atoi(optarg); break;
|
||||
case 'd': device = optarg; break;
|
||||
case 'h': help(0); exit(0);
|
||||
default:
|
||||
fprintf(stderr, "%s : uh ?", argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
// XXX else {
|
||||
printf("%9ld %6d %6d %02x\n",
|
||||
time(NULL), foo, to, byte);
|
||||
// XXX }
|
||||
|
||||
}
|
||||
|
||||
if (verbosity) {
|
||||
fprintf(stderr, "Testing Serial Software - compiled " \
|
||||
__DATE__ " " __TIME__ "\n");
|
||||
}
|
||||
|
||||
serial_in = prepare_UART(device, speed);
|
||||
if (serial_in < 0) {
|
||||
fprintf(stderr, "%s : open device : error %d on %s\n",
|
||||
argv[0], serial_in, device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "going to listen on %d\n", serial_in);
|
||||
|
||||
(void)loop(serial_in, nbre);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
66
simulator/rdtemp/rdtemp.ino
Normal file
66
simulator/rdtemp/rdtemp.ino
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* lecture des capteurs de temperature LM35
|
||||
*/
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#define NBVAL 4
|
||||
#define DELAI 5000
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
Serial.print("\n");
|
||||
/* XXX */
|
||||
/* changing the voltage reference of the ADC
|
||||
* greatly increase the prcision on the limited
|
||||
* range of our temperatures.
|
||||
*/
|
||||
analogReference(INTERNAL1V1); // Pour Arduino Mega2560
|
||||
|
||||
delay(1000);
|
||||
Serial.print("M running\n");
|
||||
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
/* ================================================== */
|
||||
short adc_pins[] = { A0, A1, A2, A4 };
|
||||
/* -------------------------------------------------- */
|
||||
void updatevalues(short *ptr)
|
||||
{
|
||||
int foo;
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
for (foo=0; foo<NBVAL; foo++) {
|
||||
ptr[foo] = analogRead(adc_pins[foo]);
|
||||
delay(100);
|
||||
}
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
void sendvalues(short *ptr)
|
||||
{
|
||||
int foo;
|
||||
|
||||
Serial.print("T");
|
||||
for (foo=0; foo<NBVAL; foo++) {
|
||||
Serial.print(" ");
|
||||
Serial.print(ptr[foo]);
|
||||
}
|
||||
Serial.print("\n");
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
void update_and_send(void)
|
||||
{
|
||||
short values[NBVAL];
|
||||
|
||||
updatevalues(values);
|
||||
sendvalues(values);
|
||||
}
|
||||
/* ================================================== */
|
||||
void loop() {
|
||||
update_and_send();
|
||||
delay(DELAI);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
55
simulator/send-random/send-random.ino
Normal file
55
simulator/send-random/send-random.ino
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* simulateur de telemesure automate
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#define NBVAL 4
|
||||
#define DELAI 1789
|
||||
|
||||
int values[NBVAL];
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
void setup() {
|
||||
int foo;
|
||||
Serial.begin(9600);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
for (foo=0; foo<NBVAL; foo++) {
|
||||
values[foo] = 0;
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
void updatevalues(void)
|
||||
{
|
||||
int foo;
|
||||
for (foo=0; foo<NBVAL; foo++) {
|
||||
if (rand()%100<42) {
|
||||
values[foo] += (foo + 1);
|
||||
}
|
||||
if (values[foo] > 1023) {
|
||||
values[foo] = rand()%5;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
void sendvalues(void)
|
||||
{
|
||||
int foo;
|
||||
char ligne[100];
|
||||
|
||||
sprintf(ligne, "X %d %d %d %d",
|
||||
values[0], values[1],values[2],values[3]);
|
||||
|
||||
Serial.println(ligne);
|
||||
}
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
void loop() {
|
||||
updatevalues();
|
||||
sendvalues();
|
||||
delay(DELAI);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
0
storage/Makefile
Normal file
0
storage/Makefile
Normal file
0
storage/t.c
Normal file
0
storage/t.c
Normal file
153
viz/curses/7segments.c
Normal file
153
viz/curses/7segments.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* DD2 Monitoring
|
||||
*
|
||||
* ncurses seven segment display
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int aff7segs_base(WINDOW * win, int lig, int col, int bits, int k)
|
||||
{
|
||||
int numbit, mask;
|
||||
int foo;
|
||||
|
||||
for (foo=0; foo<9; foo++) {
|
||||
mvwhline(win, lig+foo, col, '~', 6);
|
||||
}
|
||||
|
||||
#define KC '+'
|
||||
#define KS "++++"
|
||||
|
||||
wstandout(win);
|
||||
for (numbit=0; numbit<8; numbit++) {
|
||||
mask = 1 << numbit;
|
||||
switch(mask & bits) {
|
||||
case 0x01:
|
||||
mvwaddstr(win, lig, col+1, KS);
|
||||
break;
|
||||
case 0x02:
|
||||
mvwaddch(win, lig+1, col+5, KC);
|
||||
mvwaddch(win, lig+2, col+5, KC);
|
||||
mvwaddch(win, lig+3, col+5, KC);
|
||||
break;
|
||||
case 0x04:
|
||||
mvwaddch(win, lig+5, col+5, KC);
|
||||
mvwaddch(win, lig+6, col+5, KC);
|
||||
mvwaddch(win, lig+7, col+5, KC);
|
||||
break;
|
||||
case 0x08:
|
||||
mvwaddstr(win, lig+8, col+1, KS);
|
||||
break;
|
||||
case 0x10:
|
||||
mvwaddch(win, lig+5, col, KC);
|
||||
mvwaddch(win, lig+6, col, KC);
|
||||
mvwaddch(win, lig+7, col, KC);
|
||||
break;
|
||||
case 0x20:
|
||||
mvwaddch(win, lig+1, col , KC);
|
||||
mvwaddch(win, lig+2, col , KC);
|
||||
mvwaddch(win, lig+3, col , KC);
|
||||
break;
|
||||
case 0x40:
|
||||
mvwaddstr(win, lig+4, col+1, KS);
|
||||
break;
|
||||
case 0x80:
|
||||
/* decimal point */
|
||||
mvwaddch(win, lig+7, col+2 , KC);
|
||||
mvwaddch(win, lig+7, col+3 , KC);
|
||||
mvwaddch(win, lig+8, col+2 , KC);
|
||||
mvwaddch(win, lig+8, col+3 , KC);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
wstandend(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int aff7segs_digit(WINDOW * win, int lig, int col, char digit)
|
||||
{
|
||||
int bits;
|
||||
|
||||
#if TRACE > 1
|
||||
fprintf(stderr, ">>> %s ( %p %d %d '%c' )\n", __func__,
|
||||
win, lig, col, digit);
|
||||
#endif
|
||||
|
||||
if (isxdigit(digit)) digit = toupper(digit);
|
||||
|
||||
switch (digit) {
|
||||
case '0': bits = 0x3f; break;
|
||||
case '1': bits = 0x06; break;
|
||||
case '2': bits = 0x5b; break;
|
||||
case '3': bits = 0x4f; break;
|
||||
case '4': bits = 0x66; break;
|
||||
case '5': bits = 0x6d; break;
|
||||
case '6': bits = 0x7d; break;
|
||||
case '7': bits = 0x07; break;
|
||||
case '8': bits = 0x7f; break;
|
||||
case '9': bits = 0x6f; break;
|
||||
|
||||
/* hexadecimal letters */
|
||||
case 'A': bits = 0x77; break;
|
||||
case 'B': bits = 0x7c; break;
|
||||
case 'C': bits = 0x39; break;
|
||||
case 'D': bits = 0x5e; break;
|
||||
case 'E': bits = 0x79; break;
|
||||
case 'F': bits = 0x71; break;
|
||||
|
||||
case ' ': bits = 0; break;
|
||||
case '.': bits = 0x80; break;
|
||||
case '-': bits = 0x40; break;
|
||||
|
||||
default: bits = 0x49; break;
|
||||
}
|
||||
|
||||
aff7segs_base(win, lig, col, bits, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int aff7segs_short(WINDOW * win, int lig, int col, short value)
|
||||
{
|
||||
char buff[10];
|
||||
int idx;
|
||||
|
||||
sprintf(buff, "%6d", value);
|
||||
// mvwaddstr(win, lig-1, col, buff);
|
||||
for (idx=0; idx<strlen(buff); idx++) {
|
||||
aff7segs_digit(win, lig, col+(idx*9), buff[idx]);
|
||||
}
|
||||
wrefresh(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int aff7segs_float(WINDOW * win, int lig, int col, float value)
|
||||
{
|
||||
char buff[10];
|
||||
int idx;
|
||||
|
||||
sprintf(buff, "%6.2f", value);
|
||||
// mvwaddstr(win, lig-1, col, buff);
|
||||
for (idx=0; idx<strlen(buff); idx++) {
|
||||
aff7segs_digit(win, lig, col+(idx*9), buff[idx]);
|
||||
}
|
||||
wrefresh(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
36
viz/curses/Makefile
Normal file
36
viz/curses/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
# --------------- ***
|
||||
|
||||
COPT = -Wall -g -fpic -DTRACE=0
|
||||
OBJS = ecran.o 7segments.o waterfall.o vumetre.o \
|
||||
minidigits.o
|
||||
|
||||
ALIB = ../libdd2m-viz.a
|
||||
|
||||
# --------------- ***
|
||||
|
||||
${ALIB}: ${OBJS}
|
||||
ar r $@ $?
|
||||
|
||||
# --------------- ***
|
||||
|
||||
ecran.o: ecran.c Makefile ecran.h
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
7segments.o: 7segments.c Makefile ecran.h
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
waterfall.o: waterfall.c Makefile ecran.h
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
vumetre.o: vumetre.c Makefile ecran.h
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
minidigits.o: minidigits.c Makefile ecran.h
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
# --------------- ***
|
||||
|
||||
t: t.c Makefile $(ALIB) ecran.h
|
||||
gcc $(COPT) $< $(ALIB) -lncurses -o $@
|
||||
|
||||
# --------------- ***
|
2
viz/curses/README.md
Normal file
2
viz/curses/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Dataviz with AsciiArt
|
||||
|
76
viz/curses/ecran.c
Normal file
76
viz/curses/ecran.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int message(char *txt)
|
||||
{
|
||||
static int pass = 0;
|
||||
|
||||
#if TRACE
|
||||
fprintf(stderr, "%s [%s]\n", __func__, txt);
|
||||
#endif
|
||||
|
||||
standout();
|
||||
mvhline(LINES-1, 0, ' ', COLS);
|
||||
mvaddch(LINES-1, 0, "\\|/-"[(pass++)%4]);
|
||||
mvaddstr(LINES-1, 2, txt);
|
||||
standend();
|
||||
refresh();
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
void barre_inverse(char c, int ligne)
|
||||
{
|
||||
int foo;
|
||||
standout();
|
||||
for (foo=0; foo<COLS; foo++)
|
||||
mvaddch(ligne, foo, c);
|
||||
standend();
|
||||
/* refresh(); */
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* make display on the standard screen (stdscr) */
|
||||
int fond_ecran(char *title)
|
||||
{
|
||||
char *tp;
|
||||
struct utsname utsn;
|
||||
int foo;
|
||||
char buffer[200];
|
||||
|
||||
tp = " DD2 Monitoring by tTh 2019 ";
|
||||
if (NULL != title) tp = title;
|
||||
|
||||
barre_inverse(' ', 0);
|
||||
standout();
|
||||
mvaddstr(0, 2, tp);
|
||||
|
||||
if (verbosity) {
|
||||
sprintf(buffer, " ecr: %dx%d ", COLS, LINES);
|
||||
fprintf(stderr, "%s ==> %s\n", __func__, buffer);
|
||||
foo = strlen(buffer);
|
||||
mvaddstr(0, COLS-2-foo, buffer);
|
||||
}
|
||||
|
||||
/* get and display hostname */
|
||||
foo = uname(&utsn);
|
||||
if ( !foo ) {
|
||||
mvaddstr(0, 2+strlen(tp), "on");
|
||||
mvaddstr(0, 5+strlen(tp), utsn.nodename);
|
||||
}
|
||||
|
||||
standend();
|
||||
refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
23
viz/curses/ecran.h
Normal file
23
viz/curses/ecran.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* interface ncurses pour dd2 monitoring
|
||||
*/
|
||||
|
||||
int fond_ecran(char *titre);
|
||||
int message(char *);
|
||||
|
||||
int aff7segs_base(WINDOW * win, int lig, int col, int bits, int k);
|
||||
int aff7segs_digit(WINDOW * win, int lig, int col, char digit);
|
||||
int aff7segs_short(WINDOW * win, int lig, int col, short value);
|
||||
int aff7segs_float(WINDOW * win, int lig, int col, float value);
|
||||
|
||||
int minidigit_0(WINDOW *win, int lig, int col, char digit, int k);
|
||||
int minidigit_HMS(WINDOW *win, int lig, int col, int k);
|
||||
|
||||
|
||||
WINDOW * open_waterfall(char *title, int flags);
|
||||
int plot_waterfall(WINDOW *wf, int flags, float values[4]);
|
||||
int close_waterfall(WINDOW *wf, int notused);
|
||||
|
||||
|
||||
int vumetre_0(WINDOW * win, int lig, int col, float val, int larg);
|
||||
int vumetre_1(WINDOW * win, int lig, int col, float val, int larg);
|
107
viz/curses/minidigits.c
Normal file
107
viz/curses/minidigits.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* DD2 Monitoring
|
||||
*
|
||||
* mini digits
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
static void makedot(WINDOW *win, int li, int col, int ch)
|
||||
{
|
||||
if ('_'==ch) {
|
||||
mvwaddch(win, li, col, ' ');
|
||||
mvwaddch(win, li, col+1, ' ');
|
||||
}
|
||||
else {
|
||||
wstandout(win);
|
||||
mvwaddch(win, li, col, '+');
|
||||
mvwaddch(win, li, col+1, '+');
|
||||
wstandend(win);
|
||||
}
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
int minidigit_0(WINDOW *win, int lig, int col, char digit, int k)
|
||||
{
|
||||
static char LX[] = "_X_X_X_X_X_X_X_";
|
||||
static char L0[] = "XXXX_XX_XX_XXXX";
|
||||
static char L1[] = "_X__X__X__X__X_";
|
||||
static char L2[] = "XXX__XXXXX__XXX";
|
||||
static char L3[] = "XXX__XXXX__XXXX";
|
||||
static char L4[] = "X_XX_XXXX__X__X";
|
||||
static char L5[] = "XXXX__XXX__XXXX";
|
||||
static char L6[] = "XXXX__XXXX_XXXX";
|
||||
static char L7[] = "XXX__X__X__X__X";
|
||||
static char L8[] = "XXXX_XXXXX_XXXX";
|
||||
static char L9[] = "XXXX_XXXX__XXXX";
|
||||
|
||||
static char Lsp[] = "_______________"; /* space */
|
||||
static char Lmo[] = "______XXX______"; /* moins */
|
||||
static char Lco[] = "____X_____X____"; /* colomn */
|
||||
static char Ldp[] = "_____________X_"; /* decimal dot */
|
||||
|
||||
char *cptr;
|
||||
int l, c;
|
||||
|
||||
switch (digit) {
|
||||
|
||||
case '0': cptr = L0; break;
|
||||
case '1': cptr = L1; break;
|
||||
case '2': cptr = L2; break;
|
||||
case '3': cptr = L3; break;
|
||||
case '4': cptr = L4; break;
|
||||
case '5': cptr = L5; break;
|
||||
case '6': cptr = L6; break;
|
||||
case '7': cptr = L7; break;
|
||||
case '8': cptr = L8; break;
|
||||
case '9': cptr = L9; break;
|
||||
|
||||
case ' ': cptr = Lsp; break;
|
||||
case '-': cptr = Lmo; break;
|
||||
case ':': cptr = Lco; break;
|
||||
case '.': cptr = Ldp; break;
|
||||
|
||||
default: cptr = LX; break;
|
||||
|
||||
}
|
||||
|
||||
for (l=0; l<5; l++) {
|
||||
for (c=0; c<3; c++) {
|
||||
|
||||
makedot(win, l+lig, (c*2)+col, *cptr++);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
wrefresh(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int minidigit_HMS(WINDOW *win, int lig, int col, int k)
|
||||
{
|
||||
int foo;
|
||||
char chaine[20];
|
||||
struct tm *p_tms;
|
||||
time_t temps;
|
||||
|
||||
temps = time(NULL);
|
||||
p_tms = localtime(&temps);
|
||||
(void)strftime(chaine, 19, "%H:%M:%S", p_tms);
|
||||
for (foo=0; foo<strlen(chaine); foo++) {
|
||||
minidigit_0(stdscr, lig, col+foo*8, chaine[foo], 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
240
viz/curses/t.c
Normal file
240
viz/curses/t.c
Normal file
@ -0,0 +1,240 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int demo_minidigits(int nbl, int k)
|
||||
{
|
||||
int loop, foo;
|
||||
char chaine[100];
|
||||
|
||||
for (loop=0; loop<nbl; loop++) {
|
||||
|
||||
sprintf(chaine, "== %06X ==", loop);
|
||||
message(chaine);
|
||||
|
||||
sprintf(chaine, ".%08d.", rand()%1000000);
|
||||
|
||||
for (foo=0; foo<10; foo++) {
|
||||
minidigit_0(stdscr, 5, 2+foo*8, chaine[foo], 0);
|
||||
}
|
||||
wrefresh(stdscr);
|
||||
usleep(350*1000);
|
||||
|
||||
for (foo=0; foo<10; foo++) {
|
||||
minidigit_0(stdscr, 5, 2+foo*8, ' ', 0);
|
||||
}
|
||||
|
||||
minidigit_HMS(stdscr, 15, 9, 0);
|
||||
|
||||
wrefresh(stdscr);
|
||||
usleep(250*1000);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int demo_composite(int nbl, int k)
|
||||
{
|
||||
int loop, foo;
|
||||
short sval;
|
||||
char ligne[120];
|
||||
float fval;
|
||||
|
||||
for (loop=0; loop<nbl; loop++) {
|
||||
sval = (short)((loop % 1024)-512);
|
||||
|
||||
foo = aff7segs_short(stdscr, 5, 3, sval);
|
||||
if (foo) message("KRKRK aff7 short");
|
||||
|
||||
fval = (float)sval / 1024.0;
|
||||
foo = aff7segs_float(stdscr, 16, 3, fval);
|
||||
if (foo) message("KRKRK aff7 float");
|
||||
|
||||
fval = fabs(fval);
|
||||
foo = vumetre_0(stdscr, 29, 5, fval, COLS-10);
|
||||
|
||||
sprintf(ligne, "%04x", loop);
|
||||
mvaddstr(2, 1, ligne);
|
||||
refresh();
|
||||
usleep(200*1000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
void demo_7segments(int nbl, int notused)
|
||||
{
|
||||
int loop, idx, foo;
|
||||
char ligne[120];
|
||||
time_t temps;
|
||||
struct tm *p_tms;
|
||||
|
||||
for (loop=0; loop<nbl; loop++) {
|
||||
sprintf(ligne, "%04x", loop);
|
||||
mvaddstr(2, 1, ligne);
|
||||
for (idx=0; idx<strlen(ligne); idx++) {
|
||||
aff7segs_digit(stdscr, 3, 10+(idx*9), ligne[idx]);
|
||||
}
|
||||
|
||||
sprintf(ligne, "%.3f", drand48());
|
||||
mvaddstr(13, 1, ligne);
|
||||
for (idx=0; idx<strlen(ligne); idx++) {
|
||||
aff7segs_digit(stdscr, 14, 10+(idx*9), ligne[idx]);
|
||||
}
|
||||
|
||||
if (verbosity && (loop%2)) {
|
||||
temps = time(NULL);
|
||||
p_tms = localtime(&temps);
|
||||
foo = strftime(ligne, 100, "%F %H:%M", p_tms);
|
||||
// sprintf(ligne, "%12ld | %s", temps, ctime(&temps));
|
||||
message(ligne);
|
||||
}
|
||||
|
||||
refresh();
|
||||
usleep(400*1000);
|
||||
}
|
||||
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
void demo_vumetres(int nbl, int notused)
|
||||
{
|
||||
int loop, idx;
|
||||
int hpos;
|
||||
char ligne[100];
|
||||
float value;
|
||||
time_t temps;
|
||||
|
||||
for (loop=0; loop<nbl; loop++) {
|
||||
|
||||
value = (float)loop / (float)nbl;
|
||||
|
||||
for (idx=0; idx<8; idx++) {
|
||||
|
||||
hpos = 4 * (idx+1);
|
||||
value = drand48();
|
||||
|
||||
if (idx<4) vumetre_0(stdscr, hpos, 12, value, 60);
|
||||
else vumetre_1(stdscr, hpos, 12, value, 60);
|
||||
|
||||
}
|
||||
|
||||
if (verbosity && (loop%2)) {
|
||||
temps = time(NULL);
|
||||
sprintf(ligne, "%12ld | %s", temps, ctime(&temps));
|
||||
message(ligne);
|
||||
}
|
||||
|
||||
refresh();
|
||||
usleep(200*1000);
|
||||
}
|
||||
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
void demo_waterfall(int nbl, int k)
|
||||
{
|
||||
int loop, foo;
|
||||
char line[100];
|
||||
WINDOW *water;
|
||||
static float rvals[4];
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 200 * 1000 * 1000;
|
||||
|
||||
water = open_waterfall("premier essai", 0);
|
||||
|
||||
for (loop=0; loop<nbl; loop++) {
|
||||
|
||||
sprintf(line, " %06X %04X ", loop, rand()&0xffff);
|
||||
message(line);
|
||||
|
||||
wrefresh(stdscr);
|
||||
|
||||
for (foo=0; foo<4; foo++) {
|
||||
if (rand()%100<42) {
|
||||
rvals[foo] += 4.04 * (foo + 1);
|
||||
}
|
||||
if (rvals[foo] > 1023.0) {
|
||||
rvals[foo] = (float)(rand() % 25);
|
||||
}
|
||||
}
|
||||
|
||||
plot_waterfall(water, 1, rvals);
|
||||
|
||||
/* if (rand()%10 < 1) sleep(1); */
|
||||
foo = nanosleep(&ts, NULL);
|
||||
if (foo) {
|
||||
/* got a signal ? */
|
||||
message("err on nanosleep");
|
||||
}
|
||||
}
|
||||
|
||||
close_waterfall(water, 0);
|
||||
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
static void finish(int signal)
|
||||
{
|
||||
endwin(); exit(0);
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
int demonum = 0;
|
||||
int nb_loops = 200;
|
||||
|
||||
/* set some default values */
|
||||
verbosity = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "n:vy:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'n': nb_loops = atoi(optarg); break;
|
||||
|
||||
case 'v': verbosity++; break;
|
||||
|
||||
case 'y': demonum = atoi(optarg); break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s : uh ?", argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
initscr();
|
||||
nonl(); cbreak(); noecho();
|
||||
|
||||
keypad(stdscr, TRUE); /* acces aux touches 'curseur' */
|
||||
|
||||
fond_ecran(" Demonstrator ");
|
||||
|
||||
switch (demonum) {
|
||||
case 0: demo_vumetres(nb_loops, 0); break;
|
||||
case 1: demo_waterfall(nb_loops, 0); break;
|
||||
case 2: demo_7segments(nb_loops, 0); break;
|
||||
case 3: demo_composite(nb_loops, 0); break;
|
||||
case 4: demo_minidigits(nb_loops, 0); break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "eyecandy #%d don't exist\n", demonum);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* plop, on a fini, restaurer la console
|
||||
*/
|
||||
finish(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
88
viz/curses/vumetre.c
Normal file
88
viz/curses/vumetre.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* DD2 Monitoring
|
||||
*
|
||||
* ncurses seven segment display
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int vumetre_0(WINDOW *win, int lig, int col, float val, int larg)
|
||||
{
|
||||
int foo, posc, c;
|
||||
char ligne[100];
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, ">>> %s ( %p %d %d %f %d )\n",
|
||||
__func__, win, lig, col, val, larg);
|
||||
#endif
|
||||
|
||||
posc = (int)(val * (float)(larg-5));
|
||||
|
||||
sprintf(ligne, "%6.3f", val);
|
||||
mvwaddstr(win, lig, 0, ligne);
|
||||
|
||||
for (foo=0; foo<larg; foo++) {
|
||||
c = col + foo + 2;
|
||||
if (foo<posc) {
|
||||
wstandout(win);
|
||||
mvwaddch(win, lig, c, '#');
|
||||
wstandend(win);
|
||||
}
|
||||
else {
|
||||
mvwaddch(win, lig, c, ' ');
|
||||
}
|
||||
if (!(foo%4)) {
|
||||
mvwaddch(win, lig-1, c, '\\');
|
||||
mvwaddch(win, lig+1, c, '/');
|
||||
}
|
||||
}
|
||||
wrefresh(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int vumetre_1(WINDOW *win, int lig, int col, float val, int larg)
|
||||
{
|
||||
int foo, posc;
|
||||
char ligne[100];
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, ">>> %s ( %p %d %d %f %d )\n",
|
||||
__func__, win, lig, col, val, larg);
|
||||
#endif
|
||||
|
||||
posc = (int)(val * (float)larg);
|
||||
|
||||
sprintf(ligne, "%6.3f", val);
|
||||
mvwaddstr(win, lig, 2, ligne);
|
||||
|
||||
for (foo=0; foo<larg; foo++) {
|
||||
if (foo < posc) {
|
||||
wstandout(win);
|
||||
mvwaddch(win, lig, col+foo, '|');
|
||||
wstandend(win);
|
||||
}
|
||||
else {
|
||||
mvwaddch(win, lig, col+foo, '|');
|
||||
}
|
||||
if (foo & 2) {
|
||||
mvwaddch(win, lig-1, col+foo, '|');
|
||||
mvwaddch(win, lig+1, col+foo, '|');
|
||||
}
|
||||
}
|
||||
wrefresh(win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
117
viz/curses/waterfall.c
Normal file
117
viz/curses/waterfall.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* DD2 Monitoring
|
||||
*
|
||||
* ncurses waterfall interface
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
|
||||
#include "ecran.h"
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
WINDOW *open_waterfall(char *title, int flags)
|
||||
{
|
||||
WINDOW *win;
|
||||
int l, c, w, h;
|
||||
|
||||
l = 1; c = 1;
|
||||
w = COLS; h = LINES - 3;
|
||||
|
||||
win = newwin(h, w, l, c);
|
||||
scrollok(win, 1);
|
||||
waddstr(win, title); waddch(win, '\n');
|
||||
wrefresh(win);
|
||||
|
||||
return win;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int plot_waterfall(WINDOW *wf, int mode, float values[4])
|
||||
{
|
||||
#define TL 1000
|
||||
int foo, idx;
|
||||
char tag, ligne[TL+1];
|
||||
float coef_w;
|
||||
static long iter;
|
||||
|
||||
if (0 == (iter%10)) {
|
||||
memset(ligne, '.', TL);
|
||||
}
|
||||
else {
|
||||
memset(ligne, ' ', TL);
|
||||
}
|
||||
for (foo=0; foo<500; foo+=20) {
|
||||
ligne[foo] = '.';
|
||||
}
|
||||
ligne[COLS-1] = '\0';
|
||||
|
||||
iter++;
|
||||
|
||||
coef_w = (float)(COLS-1) / 1024.0;
|
||||
|
||||
#if TRACE > 1
|
||||
fprintf(stderr, "COLS = %d, coef_w = %f\n", COLS, coef_w);
|
||||
#endif
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case 0: default:
|
||||
sprintf(ligne, "%11.3f %11.3f %11.3f %11.3f",
|
||||
values[0], values[1], values[2], values[3]);
|
||||
#if TRACE
|
||||
fprintf(stderr, "%s [%s]\n", __func__, ligne);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 1:
|
||||
for(foo=0; foo<4; foo++) {
|
||||
tag = "ATOX"[foo];
|
||||
idx = (int)(values[foo]*coef_w);
|
||||
ligne[idx] = tag;
|
||||
#if TRACE
|
||||
fprintf(stderr, "%c %3d ", tag, idx);
|
||||
#endif
|
||||
}
|
||||
ligne[COLS-1] = '\0';
|
||||
#if TRACE
|
||||
fprintf(stderr, "\n"); fflush(stderr);
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* poke the text in the curses window */
|
||||
// scroll(wf);
|
||||
waddstr(wf, ligne); waddch(wf, '\n');
|
||||
wrefresh(wf);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
||||
int close_waterfall(WINDOW *wf, int notused)
|
||||
{
|
||||
int foo;
|
||||
|
||||
if (NULL == wf) {
|
||||
fprintf(stderr, "%s wf is null\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
foo = delwin(wf);
|
||||
if (ERR==foo) {
|
||||
fprintf(stderr, "%s : err on delwin\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ---------------------------------------------------------------- */
|
34
viz/gnuplot/av4v-h.awk
Executable file
34
viz/gnuplot/av4v-h.awk
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
BEGIN {
|
||||
flag_debut = 1;
|
||||
lasthour = 0;
|
||||
cumul = 0.0;
|
||||
compte = 0;
|
||||
}
|
||||
|
||||
# iterate over all the input lines
|
||||
{
|
||||
if (flag_debut) {
|
||||
debut = $1
|
||||
flag_debut = 0
|
||||
}
|
||||
heures = int(($1-debut) / 3600);
|
||||
if (heures == lasthour) {
|
||||
val = ($2 + $3 + $4 + $5);
|
||||
cumul += val;
|
||||
compte += 4;
|
||||
}
|
||||
else {
|
||||
val = cumul /compte;
|
||||
print $1, val;
|
||||
lasthour = heures;
|
||||
cumul = 0;
|
||||
compte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
34
viz/gnuplot/average4v.awk
Executable file
34
viz/gnuplot/average4v.awk
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
BEGIN {
|
||||
flag_debut = 1;
|
||||
lastminute = 0;
|
||||
cumul = 0.0;
|
||||
compte = 0;
|
||||
}
|
||||
|
||||
# iterate over all the input lines
|
||||
{
|
||||
if (flag_debut) {
|
||||
debut = $1
|
||||
flag_debut = 0
|
||||
}
|
||||
minutes = int(($1-debut) / 60);
|
||||
if (minutes == lastminute) {
|
||||
val = ($2 + $3 + $4 + $5);
|
||||
cumul += val;
|
||||
compte += 4;
|
||||
}
|
||||
else {
|
||||
val = cumul /compte;
|
||||
print minutes, val;
|
||||
lastminute = minutes;
|
||||
cumul = 0;
|
||||
compte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
22
viz/gnuplot/plot-one.sh
Executable file
22
viz/gnuplot/plot-one.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
INFILE="../../serial/foo.dat"
|
||||
NBLINES=1600
|
||||
TMPFILE="/tmp/dd2data.$$"
|
||||
IMAGE="av4v-m.png"
|
||||
|
||||
tail -${NBLINES} ${INFILE} | ./average4v.awk > ${TMPFILE}
|
||||
|
||||
gnuplot << __EOC__
|
||||
set term png size 1280,420
|
||||
set output "${IMAGE}"
|
||||
set grid
|
||||
set title "Average on the last ${NBLINES} samples"
|
||||
set xlabel "Minutes"
|
||||
set ylabel "Température"
|
||||
set yrange [ 5.0 : 30.0]
|
||||
plot "${TMPFILE}" with lines
|
||||
__EOC__
|
||||
|
||||
tail -20 ${TMPFILE}
|
||||
|
27
viz/gnuplot/plot-two.sh
Executable file
27
viz/gnuplot/plot-two.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
INFILE="../../serial/foo.dat"
|
||||
NBLINES=60000
|
||||
TMPFILE="/tmp/dd2data.$$"
|
||||
IMAGE="av4v-h.png"
|
||||
|
||||
tail -${NBLINES} ${INFILE} | ./av4v-h.awk > ${TMPFILE}
|
||||
|
||||
gnuplot << __EOC__
|
||||
set term png size 1280,420
|
||||
set output "${IMAGE}"
|
||||
set grid
|
||||
set title "Hourly average on the last ${NBLINES} samples"
|
||||
set xlabel "Heures"
|
||||
set ylabel "Temperature"
|
||||
set yrange [ 0.0 : 30.0]
|
||||
|
||||
set xdata time
|
||||
set timefmt "%s"
|
||||
set format x "%d, %H:%M"
|
||||
|
||||
plot "${TMPFILE}" using 1:2 title "celcius" with lines
|
||||
__EOC__
|
||||
|
||||
cat -n ${TMPFILE} | tail -20
|
||||
|
3
viz/pg/README.md
Normal file
3
viz/pg/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Visualisation avec PyGame
|
||||
|
||||
Welcome on-board, Claire !
|
Loading…
Reference in New Issue
Block a user