je vais tout casser ?
This commit is contained in:
commit
975e501d9b
18
.gitignore
vendored
18
.gitignore
vendored
@ -2,9 +2,25 @@ a.out
|
|||||||
*.o
|
*.o
|
||||||
fake-values
|
fake-values
|
||||||
essai
|
essai
|
||||||
|
foo.dat
|
||||||
serial/t
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
15
Makefile
15
Makefile
@ -3,18 +3,19 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
CCOPT = -Wall -g
|
CCOPT = -Wall -g
|
||||||
|
CLIB = core/libdd2m-core.a viz/libdd2m-viz.a
|
||||||
|
|
||||||
all: essai fake-values
|
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
|
essai: essai.c Makefile $(CLIB)
|
||||||
gcc ${CCOPT} -c $<
|
$(CC) ${CCOPT} $< $(CLIB) ${O} -lncurses -o $@
|
||||||
|
|
||||||
fake-values: fake-values.c funcs.o Makefile
|
fake-values: fake-values.c Makefile $(CLIB)
|
||||||
gcc ${CCOPT} $< funcs.o -o $@
|
$(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
|
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
|
automate de contrôle de l'enceinte thermostatée. Nous devrons
|
||||||
|
<<<<<<< HEAD
|
||||||
surveiller température et humidité du dd2, et température du
|
surveiller température et humidité du dd2, et température du
|
||||||
confinement biologique.
|
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
|
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
|
`#tetalab` sur le réseau Freenode et/ou les rencontres du mercredi
|
||||||
soir au DD2, à Mixart-Myrys.
|
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>
|
#include <stdio.h>
|
||||||
@ -9,8 +9,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "funcs.h"
|
|
||||||
|
|
||||||
extern int verbosity;
|
extern int verbosity;
|
||||||
|
|
||||||
/* --------------------------------------------------------------- */
|
/* --------------------------------------------------------------- */
|
||||||
@ -25,9 +23,11 @@ return v1 ^ v2;
|
|||||||
/* --------------------------------------------------------------- */
|
/* --------------------------------------------------------------- */
|
||||||
int random1000(int type)
|
int random1000(int type)
|
||||||
{
|
{
|
||||||
int value;
|
int value, foo;
|
||||||
if (verbosity)
|
|
||||||
|
#if DEBUG_LEVEL > 1
|
||||||
fprintf(stderr, ">>> %s(%d)\n", __func__, type);
|
fprintf(stderr, ">>> %s(%d)\n", __func__, type);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -36,6 +36,12 @@ switch (type) {
|
|||||||
case 1:
|
case 1:
|
||||||
value = (rand()%1000 + rand()%1000) / 2;
|
value = (rand()%1000 + rand()%1000) / 2;
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
value = 0;
|
||||||
|
for (foo=0; foo<4; foo++)
|
||||||
|
value += rand() % 1000;
|
||||||
|
value /= 4;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
value = -1;
|
value = -1;
|
||||||
break;
|
break;
|
||||||
@ -43,9 +49,7 @@ switch (type) {
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------- */
|
/* --------------------------------------------------------------- */
|
||||||
|
|
||||||
double dtime(void)
|
double dtime(void)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
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;
|
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,11pt]{article}
|
||||||
\documentclass[a4paper,12pt]{article}
|
|
||||||
|
|
||||||
% \listfiles % pour le debug
|
% \listfiles % pour le debug
|
||||||
|
|
||||||
@ -8,13 +7,14 @@
|
|||||||
\usepackage[T1]{fontenc}
|
\usepackage[T1]{fontenc}
|
||||||
% XXX \usepackage{lipsum}
|
% XXX \usepackage{lipsum}
|
||||||
\usepackage{makeidx}
|
\usepackage{makeidx}
|
||||||
|
\usepackage{listings}
|
||||||
% \usepackage{color}
|
% \usepackage{color}
|
||||||
% \usepackage{url}
|
% \usepackage{url}
|
||||||
\usepackage{xspace}
|
\usepackage{xspace}
|
||||||
\usepackage[verbose]{layout}
|
\usepackage[verbose]{layout}
|
||||||
|
|
||||||
\makeindex
|
\makeindex
|
||||||
\setlength{\parskip}{0.25cm plus 0.25cm}
|
% \setlength{\parskip}{0.16cm plus 0.16cm}
|
||||||
|
|
||||||
% -------------------------------------------------------------------
|
% -------------------------------------------------------------------
|
||||||
\title{DD2 Monitoring}
|
\title{DD2 Monitoring}
|
||||||
@ -25,6 +25,12 @@
|
|||||||
|
|
||||||
\pagebreak
|
\pagebreak
|
||||||
|
|
||||||
|
% \setlength{\parskip}{0.01cm plus 0.01cm}
|
||||||
|
\tableofcontents
|
||||||
|
% \setlength{\parskip}{0.16cm plus 0.16cm}
|
||||||
|
|
||||||
|
\pagebreak
|
||||||
|
|
||||||
% -------------------------------------------------------------------
|
% -------------------------------------------------------------------
|
||||||
|
|
||||||
\section{Introduction}
|
\section{Introduction}
|
||||||
@ -41,45 +47,85 @@ arrivons parfois à le faire.
|
|||||||
|
|
||||||
La première étape sera donc la mise au point d'un \textsl{cadriciel}
|
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
|
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
|
Les valeurs à mesurer étant de diverses natures, nous aurons l'occasion
|
||||||
de découvrir plein de capteurs différents : température, humidité,
|
de découvrir plein de capteurs différents : température, humidité,
|
||||||
\texttt{pH}, transparence, lumière, vibrations\dots
|
\texttt{pH}, transparence, lumière, vibrations\dots
|
||||||
|
|
||||||
% -------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
\vspace{4cm}
|
||||||
|
|
||||||
|
Bonne lecture.
|
||||||
|
|
||||||
|
% -------------------------------------------------------------------
|
||||||
|
% ===================================================================
|
||||||
|
|
||||||
|
\pagebreak
|
||||||
\section{Présentation générale}
|
\section{Présentation générale}
|
||||||
|
|
||||||
\subsection{Capteurs} \index{capteurs}
|
\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
|
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
|
Par la suite, nous pourrons récupérer
|
||||||
en provenance de l'automate de contrôle de l'enceinte. Notre dd2monitor
|
(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,
|
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}
|
\subsection{Stockage}
|
||||||
|
|
||||||
Pour entreposer toutes ces valeurs numériques, il existe plusieurs
|
Pour entreposer toutes ces valeurs numériques, il existe plusieurs
|
||||||
choix, et nous allons en évaluer quelques uns :
|
choix, et nous allons en évaluer quelques uns~:
|
||||||
\texttt{rrdb}\index{rrdb},
|
|
||||||
\texttt{influxdb}\index{influxdb} (page \pageref{influxdb}),
|
\texttt{flatfile}\index{flatfile} (page \pageref{flatfile}),
|
||||||
\texttt{gnocchi}\index{gnocchi}...
|
\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}
|
\subsection{Affichage}
|
||||||
|
|
||||||
Nous allons laisser un petit bac-à-sable pour Fred Fermion\index{nodejs},
|
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
|
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}
|
\section{Outils}
|
||||||
|
|
||||||
\subsection{Simulations}
|
\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
|
C'est pour ça qu'il y a déja un générateur de \textit{fake-values} qui
|
||||||
ne demande qu'à grandir.
|
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}
|
\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}
|
\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
|
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.
|
Pour commencer presque simple, un exemple d'affichage avec
|
||||||
La première, que nous allons juste entrevoir, passera par le port
|
Gnuplot\index{gnuplot} d'un fichier plat
|
||||||
USB de la carte Arduino. La seconde passera par un port série
|
de température (décrit page \pageref{foo.dat}) :
|
||||||
auxiliaire\footnote{Il y en a 4 sur le 2560} de celle-ci.
|
|
||||||
|
|
||||||
|
\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}
|
||||||
|
|
||||||
|
|
||||||
% -------------------------------------------------------------------
|
% -------------------------------------------------------------------
|
||||||
|
\input{storages}
|
||||||
|
|
||||||
\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{serial}
|
||||||
|
\input{detournements}
|
||||||
% -------------------------------------------------------------------
|
% -------------------------------------------------------------------
|
||||||
|
|
||||||
\section{Conclusion} \label{conclusion} \index{conclusion}
|
\section{Conclusion} \label{conclusion} \index{conclusion}
|
||||||
|
|
||||||
En fait, tout reste à faire. Mais ça peut être un beau projet
|
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}
|
\setlength{\parskip}{0.05cm plus 0.05cm}
|
||||||
|
|
||||||
\pagebreak \tableofcontents
|
% \pagebreak \tableofcontents
|
||||||
|
|
||||||
\printindex
|
\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 ?
|
||||||
|
|
84
essai.c
84
essai.c
@ -5,32 +5,98 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt, foo;
|
int opt, foo;
|
||||||
int type = 0;
|
int serial_in;
|
||||||
double loads[3];
|
char *device = "/dev/ttyACM0";
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "vst:")) != -1) {
|
while ((opt = getopt(argc, argv, "d:hv")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case 'd': device = optarg; break;
|
||||||
|
case 'h': help(0); break;
|
||||||
case 'v': verbosity++; break;
|
case 'v': verbosity++; break;
|
||||||
case 's': srand(getpid()); break;
|
|
||||||
case 't': type = atoi(optarg); break;
|
|
||||||
default: 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
15
exemple.sh
15
exemple.sh
@ -6,21 +6,28 @@ DATAFILE=/tmp/fake-datafile
|
|||||||
> ${DATAFILE}
|
> ${DATAFILE}
|
||||||
for s in $(seq 1 1000)
|
for s in $(seq 1 1000)
|
||||||
do
|
do
|
||||||
v=$(./fake-values -s -t 1 2> /dev/null)
|
v=$(./fake-values -s -t 4)
|
||||||
echo $s $v >> ${DATAFILE}
|
echo $s $v >> ${DATAFILE}
|
||||||
done
|
done
|
||||||
|
|
||||||
|
tail -5 ${DATAFILE}
|
||||||
|
|
||||||
#----- do dome useless computations
|
#----- do dome useless computations
|
||||||
awk '
|
awk '
|
||||||
NR==1 { debut = $2 }
|
NR==1 {
|
||||||
|
debut = $2
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
# print $2-debut, $3
|
# print $2-debut, $3
|
||||||
v = int($3/25);
|
v = int($3/35);
|
||||||
bucket[v]++;
|
bucket[v]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
END {
|
END {
|
||||||
for (v=0; v<40; v++) {
|
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 "-";
|
printf "-";
|
||||||
}
|
}
|
||||||
print "*"
|
print "*"
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* fake-values.c
|
* fake-values.c
|
||||||
|
* -------------
|
||||||
|
* useless software
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "funcs.h"
|
#include "core/utils.h"
|
||||||
|
|
||||||
int verbosity;
|
int verbosity;
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ if (verbosity > 1) {
|
|||||||
fprintf(stderr, "fake values - %s %s\n", __DATE__, __TIME__);
|
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;
|
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
|
_The problem that [Gnocchi](https://gnocchi.xyz/) solves is the storage and indexing of
|
||||||
time series data and resources at a large scale.
|
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
|
This is useful in modern cloud platforms which are not only huge
|
||||||
but also are dynamic and potentially multi-tenant.
|
but also are dynamic and potentially multi-tenant.
|
||||||
Gnocchi takes all of that into account._
|
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 ?
|
# 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.
|
une visualisation dynamique des données en lancer de rayon.
|
||||||
Projet ambitieux ? Non, la suite sera bien pire.
|
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;
|
use strict;
|
||||||
|
|
||||||
|
my $host = "localhost";
|
||||||
|
my $port = 8086;
|
||||||
|
|
||||||
print "injecteur v 0\n";
|
print "injecteur v 0\n";
|
||||||
|
|
||||||
0;
|
0;
|
||||||
|
@ -1,3 +1,39 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
## Round Robin Database
|
## 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
|
serial.o: serial.c serial.h Makefile
|
||||||
gcc ${OPT} -c $<
|
gcc ${OPT} -c $<
|
||||||
|
|
||||||
t: t.c serial.o Makefile
|
funcs.o: funcs.c serial.h Makefile
|
||||||
gcc ${OPT} $< serial.o -o $@
|
gcc ${OPT} -c $<
|
||||||
|
|
||||||
|
# ---------------------------------------------------
|
||||||
|
|
||||||
|
t: t.c Makefile ${OBJS}
|
||||||
|
gcc ${OPT} $< ${OBJS} -o $@
|
||||||
|
|
||||||
|
@ -1,14 +1,45 @@
|
|||||||
|
|
||||||
# Serial Input
|
# Serial Input
|
||||||
|
|
||||||
But premier de ce module : recevoir les données fournies par l'automate
|
But premier de ce module : recevoir les données fournies par l'automate
|
||||||
de contrôle du phytotron.
|
de contrôle du phytotron.
|
||||||
|
|
||||||
Ayant déja pratiqué ce genre de chose pour un déja ancien
|
Ayant déja pratiqué ce genre de chose (recevoir des données par rs232)
|
||||||
[projet](http://art.dinorama.fr/bdf/)
|
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,
|
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.
|
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;
|
||||||
|
}
|
||||||
|
/* ---------------------------------------------------------------- */
|
103
serial/serial.c
103
serial/serial.c
@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h> //Used for UART
|
#include <unistd.h> //Used for UART
|
||||||
#include <fcntl.h> //Used for UART
|
#include <fcntl.h> //Used for UART
|
||||||
#include <termios.h> //Used for UART
|
#include <termios.h> //Used for UART
|
||||||
@ -39,7 +41,7 @@ int baudbits;
|
|||||||
struct termios options;
|
struct termios options;
|
||||||
|
|
||||||
#if DEBUG_LEVEL
|
#if DEBUG_LEVEL
|
||||||
fprintf(stderr, "%s ( %s %d )\n", __func__, port, baudrate);
|
fprintf(stderr, ">>> %s ( %s %d )\n", __func__, port, baudrate);
|
||||||
#endif
|
#endif
|
||||||
// OPEN THE UART
|
// OPEN THE UART
|
||||||
// The flags (defined in fcntl.h):
|
// 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
|
// shall not cause the terminal device to become the controlling terminal
|
||||||
// for the process.
|
// for the process.
|
||||||
|
|
||||||
uart0 = open(port, O_RDWR | O_NOCTTY);
|
uart0 = open(port, O_RDONLY | O_NOCTTY);
|
||||||
if (uart0== -1)
|
if (uart0 < 0)
|
||||||
{
|
{
|
||||||
perror("unable to open uart ");
|
perror("unable to open uart ");
|
||||||
return -1;
|
return -1;
|
||||||
@ -84,32 +86,44 @@ if (uart0== -1)
|
|||||||
|
|
||||||
|
|
||||||
baudbits = baudrate2const(baudrate);
|
baudbits = baudrate2const(baudrate);
|
||||||
#if DEBUG_LEVEL
|
#if DEBUG_LEVEL > 1
|
||||||
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
|
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
memset(&options, 0, sizeof(options));
|
||||||
|
|
||||||
tcgetattr(uart0, &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_iflag = IGNPAR;
|
||||||
options.c_oflag = 0;
|
options.c_oflag = 0;
|
||||||
options.c_lflag = 0;
|
options.c_lflag = 0;
|
||||||
|
|
||||||
|
options.c_cc[VMIN] = 1; /* ask for blocking read */
|
||||||
|
|
||||||
tcflush(uart0, TCIFLUSH);
|
tcflush(uart0, TCIFLUSH);
|
||||||
tcsetattr(uart0, TCSANOW, &options);
|
tcsetattr(uart0, TCSANOW, &options);
|
||||||
|
|
||||||
|
tcflush(uart0, TCIFLUSH); /* do it again, sam */
|
||||||
|
|
||||||
return uart0;
|
return uart0;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/*
|
/*
|
||||||
* this function have NO timeout !
|
* this function have NO timeout !
|
||||||
|
* blocking read is not blocking, wtf ?
|
||||||
*/
|
*/
|
||||||
int getbyte(int fd)
|
int getbyte(int fd)
|
||||||
{
|
{
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
int foo;
|
int foo;
|
||||||
|
|
||||||
|
byte = 0;
|
||||||
|
|
||||||
foo = read(fd, &byte, 1);
|
foo = read(fd, &byte, 1);
|
||||||
if (1 != foo)
|
if (1 != foo)
|
||||||
{
|
{
|
||||||
perror("read a byte");
|
fprintf(stderr, "byte %d rd %d errno %d\n",
|
||||||
|
byte, foo, errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return (int)byte;
|
return (int)byte;
|
||||||
@ -126,9 +140,8 @@ int retval;
|
|||||||
|
|
||||||
timeout.tv_sec = to_ms / 1000;
|
timeout.tv_sec = to_ms / 1000;
|
||||||
timeout.tv_usec = (to_ms % 1000) * 1000;
|
timeout.tv_usec = (to_ms % 1000) * 1000;
|
||||||
|
#if DEBUG_LEVEL > 1
|
||||||
#if DEBUG_LEVEL
|
fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
|
||||||
fprintf(stderr, "timeout %6d is %4ld %6ld\n", to_ms,
|
|
||||||
timeout.tv_sec, timeout.tv_usec);
|
timeout.tv_sec, timeout.tv_usec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -136,37 +149,91 @@ FD_ZERO (&rfds);
|
|||||||
FD_SET (fd, &rfds);
|
FD_SET (fd, &rfds);
|
||||||
|
|
||||||
retval = select(1, &rfds, NULL, NULL, &timeout);
|
retval = select(1, &rfds, NULL, NULL, &timeout);
|
||||||
|
|
||||||
#if DEBUG_LEVEL
|
#if DEBUG_LEVEL
|
||||||
fprintf(stderr, "%s : select -> %d\n", __func__, retval);
|
fprintf(stderr, "%s : select on fd %d -> %d\n", __func__, fd, retval);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
retval = retval < 0 ? -1 : retval;
|
|
||||||
|
|
||||||
switch (retval) {
|
switch (retval) {
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
fprintf(stderr, "omg ?\n");
|
fprintf(stderr, "omg ?\n");
|
||||||
byte = -1;
|
retval = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
fprintf(stderr, "timeout\n");
|
fprintf(stderr, "timeout %ld.%ld\n",
|
||||||
byte = -99;
|
timeout.tv_sec, timeout.tv_usec);
|
||||||
|
retval = -99;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
fprintf(stderr, "%s default -> %d\n", __func__, retval);
|
||||||
if (retval==fd) {
|
if (retval==fd) {
|
||||||
read(fd, &byte, 1);
|
read(fd, &byte, 1);
|
||||||
fprintf(stderr, "got 0x%02x\n", byte);
|
fprintf(stderr, "got 0x%02x\n", byte);
|
||||||
|
retval = byte;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "%d bad fd ?\n", retval);
|
fprintf(stderr, "%d bad fd ?\n", retval);
|
||||||
byte = -3;
|
retval = -3;
|
||||||
}
|
}
|
||||||
break;
|
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 prepare_UART(char *port, int bauds);
|
||||||
|
|
||||||
int getbyte(int fd);
|
int getbyte(int fd); /* really brotched func */
|
||||||
|
|
||||||
|
|
||||||
/* timeout is exprimed in milliseconds. */
|
/* timeout is exprimed in milliseconds. */
|
||||||
int getbyte_to (int fd, int to_ms);
|
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]);
|
||||||
|
|
||||||
|
|
||||||
|
111
serial/t.c
111
serial/t.c
@ -1,29 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Experiments with the serial input
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <time.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"
|
#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 main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int serial_in;
|
int serial_in;
|
||||||
int byte, foo, to;
|
char *device = "/dev/ttyACM0";
|
||||||
|
int nbre, speed, opt;
|
||||||
|
|
||||||
serial_in = prepare_UART("/dev/ttyS0", 9600);
|
/* set some default values */
|
||||||
fprintf(stderr, "prepare uart -> %d\n", serial_in);
|
verbosity = 0;
|
||||||
|
nbre = 25;
|
||||||
|
speed = 9600;
|
||||||
|
|
||||||
for (foo=0; foo<20; foo++) {
|
while ((opt = getopt(argc, argv, "d:n:vh")) != -1) {
|
||||||
to = (foo+1) * 666;
|
switch (opt) {
|
||||||
byte = getbyte_to(serial_in, to);
|
case 'v': verbosity++; break;
|
||||||
if (byte < 0) {
|
case 'n': nbre = atoi(optarg); break;
|
||||||
fprintf(stderr, "get byte : err is %d\n", byte);
|
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;
|
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