2025-11-30 09:48:43 +01:00
# include <unistd.h>
# include <ncurses.h>
# include <math.h>
# include <locale.h>
# include <array>
2025-12-03 23:27:56 +01:00
# include "main.hpp"
2025-11-30 09:48:43 +01:00
# include "AutomForArduino.cpp"
2025-12-03 23:20:46 +01:00
# include <prometheus/counter.h>
# include <prometheus/gauge.h>
# include <prometheus/registry.h>
# include <prometheus/exposer.h>
2025-11-30 09:48:43 +01:00
// Constantes de fonctionnement
# define LEVEL_MIN 2
# define FLOW_PER_PUMP 150
WINDOW * window ;
int etape = 10 ; // Étape du grafcet : début Automatique
int bp_mode , bp_mode_fm ;
unsigned short pompe1 , pompe2 , pompe3 , pompe4 ; // bouton des pompes 0 (arrêt) / 1 (marche)
unsigned short pompe1_old , pompe2_old , pompe3_old , pompe4_old ;
unsigned short sensor_max , sensor_high , sensor_low , sensor_min ;
float TankInitalValue = 7 ;
TemporisationRetardMontee tempo1 ( 500 ) ;
TemporisationRetardMontee tempo2 ( 1000 ) ;
TemporisationRetardMontee tempo3 ( 1500 ) ;
TemporisationRetardMontee tempo4 ( 2000 ) ;
// Prometheus
// ************************************************************
2025-12-03 23:20:46 +01:00
using namespace prometheus ;
2025-11-30 09:48:43 +01:00
2025-12-03 23:20:46 +01:00
std : : shared_ptr < Registry > registry ;
Gauge * debit_entree = nullptr ;
Gauge * debit_sortie = nullptr ;
2025-11-30 09:48:43 +01:00
// ************************************************************
2025-12-03 23:27:56 +01:00
int main ( )
2025-12-03 23:20:46 +01:00
{
2025-11-30 09:48:43 +01:00
/* Initialisation */
ConsoleInit ( ) ;
AffichageWindow ( ) ;
InitPrometheus ( ) ;
ProcessInitKeyboard ( ) ;
ProcessInitIO ( ) ;
ProcessInitValues ( ) ;
while ( 1 )
{
int ch = getch ( ) ; // Lit l'entrée du clavier sans bloquer
// **** Break loop if escape key (27) is pressed
2025-12-03 23:20:46 +01:00
if ( ch = = 27 | | _digital [ OUT_END ] . ivalue ) {
2025-11-30 09:48:43 +01:00
break ;
}
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// **** Beep
if ( _digital [ OUT_BEEP ] . ivalue )
{
beep ( ) ;
_digital [ OUT_BEEP ] . ivalue = false ;
}
Process ( ) ;
LireClavier ( ch ) ;
LireEntree ( ) ;
EvolutionGrafcet ( ) ;
Actions ( ) ;
ProcessPrometheus ( ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
ProcessException ( ) ;
usleep ( 100000 ) ;
}
endwin ( ) ; // Termine ncurses et rétablit le terminal
puts ( " Fin du programme " ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
return 0 ;
}
/**
* Programme
*/
void LireEntree ( )
{
int input ;
input = digitalRead ( IN_KEYBOARD_A ) ;
bp_mode_fm = ( input > bp_mode ) ;
bp_mode = input ;
sensor_min = digitalRead ( IN_SENSOR_MIN ) ;
sensor_low = digitalRead ( IN_SENSOR_LOW ) ;
sensor_high = digitalRead ( IN_SENSOR_HIGH ) ;
sensor_max = digitalRead ( IN_SENSOR_MAX ) ;
}
void EvolutionGrafcet ( )
{
int etape_futur = etape ;
if ( etape < 10 & & bp_mode_fm )
{
etape_futur = 10 ;
pompe1 = pompe2 = pompe3 = pompe4 = 0 ;
}
if ( etape < = 2 & & _digital [ IN_KEYBOARD_1 ] . raising )
{
pompe1 = ! pompe1 ;
}
if ( etape < = 2 & & _digital [ IN_KEYBOARD_2 ] . raising )
{
pompe2 = ! pompe2 ;
}
if ( etape < = 2 & & _digital [ IN_KEYBOARD_3 ] . raising )
{
pompe3 = ! pompe3 ;
}
if ( etape < = 2 & & _digital [ IN_KEYBOARD_4 ] . raising )
{
pompe4 = ! pompe4 ;
}
if ( etape = = 0 & & ! sensor_min )
{
etape_futur = 1 ;
}
if ( etape = = 1 )
{
etape_futur = 2 ;
}
if ( etape = = 2 & & sensor_min )
{
etape_futur = 0 ;
}
if ( etape > = 10 & & bp_mode_fm )
{
etape_futur = 0 ;
pompe1 = pompe2 = pompe3 = pompe4 = 0 ;
}
if ( sensor_max )
{
pompe1 = pompe2 = pompe3 = pompe4 = 0 ;
}
/* Automatique */
if ( etape = = 10 & & ! sensor_low & & ! sensor_high )
{
etape_futur = 11 ;
}
if ( etape = = 11 & & sensor_high )
{
etape_futur = 10 ;
}
if ( etape = = 11 & & tempo1 . getSortie ( ) )
{
etape_futur = 12 ;
}
if ( etape = = 12 & & sensor_high )
{
etape_futur = 13 ;
}
if ( etape = = 12 & & tempo2 . getSortie ( ) )
{
etape_futur = 14 ; // Allumer le moteur 2
}
if ( etape = = 13 & & tempo1 . getSortie ( ) )
{
etape_futur = 10 ;
}
if ( etape = = 13 & & ! sensor_low & & ! sensor_high )
{
etape_futur = 12 ;
}
if ( etape = = 14 & & sensor_high )
{
etape_futur = 15 ;
}
if ( etape = = 14 & & tempo3 . getSortie ( ) )
{
etape_futur = 16 ;
}
if ( etape = = 15 & & tempo1 . getSortie ( ) )
{
etape_futur = 13 ;
}
if ( etape = = 15 & & ! sensor_low & & ! sensor_high )
{
etape_futur = 14 ;
}
if ( etape = = 16 & & sensor_high )
{
etape_futur = 17 ;
}
if ( etape = = 16 & & tempo4 . getSortie ( ) )
{
etape_futur = 18 ;
}
if ( etape = = 17 & & tempo1 . getSortie ( ) )
{
etape_futur = 15 ;
}
if ( etape = = 17 & & ! sensor_low & & ! sensor_high )
{
etape_futur = 16 ;
}
if ( etape = = 18 & & sensor_high )
{
etape_futur = 19 ;
}
if ( etape = = 19 & & tempo1 . getSortie ( ) )
{
etape_futur = 17 ;
}
if ( etape = = 19 & & ! sensor_low & & ! sensor_high )
{
etape_futur = 18 ;
}
/* Fin de mode automatique */
if ( etape ! = etape_futur )
{
etape = etape_futur ;
}
}
void Actions ( )
{
digitalWrite ( OUT_DISPLAY_GRAFCET , etape ) ;
digitalWrite ( OUT_DISPLAY_MODE , etape > = 10 ) ;
digitalWrite ( OUT_PUMP_1 , ! sensor_max & & ( pompe1 = = 1 | | etape > = 12 ) ) ;
digitalWrite ( OUT_PUMP_2 , ! sensor_max & & ( pompe2 = = 1 | | etape > = 14 ) ) ;
digitalWrite ( OUT_PUMP_3 , ! sensor_max & & ( pompe3 = = 1 | | etape > = 16 ) ) ;
digitalWrite ( OUT_PUMP_4 , ! sensor_max & & ( pompe4 = = 1 | | etape > = 18 ) ) ;
// digitalWrite(OUT_BEEP, etape == 1);
if ( etape > = 11 )
{
tempo1 . activation ( ) ;
tempo2 . activation ( ) ;
tempo3 . activation ( ) ;
tempo4 . activation ( ) ;
}
}
/**
* Process
*/
void ProcessInitKeyboard ( )
{
_keyboard [ 0 ] . vKey = ' 1 ' ;
_keyboard [ 0 ] . input = IN_KEYBOARD_1 ;
_keyboard [ 1 ] . vKey = ' 2 ' ;
_keyboard [ 1 ] . input = IN_KEYBOARD_2 ;
_keyboard [ 2 ] . vKey = ' 3 ' ;
_keyboard [ 2 ] . input = IN_KEYBOARD_3 ;
_keyboard [ 3 ] . vKey = ' 4 ' ;
_keyboard [ 3 ] . input = IN_KEYBOARD_4 ;
_keyboard [ 4 ] . vKey = ' a ' ;
_keyboard [ 4 ] . input = IN_KEYBOARD_A ;
_keyboard [ 5 ] . vKey = ' x ' ;
_keyboard [ 5 ] . input = IN_KEYBOARD_X ;
_keyboard [ 6 ] . vKey = ' 6 ' ;
_keyboard [ 6 ] . input = IN_KEYBOARD_7 ;
_keyboard [ 7 ] . vKey = ' 7 ' ;
_keyboard [ 7 ] . input = IN_KEYBOARD_8 ;
_keyboard [ 8 ] . vKey = ' 8 ' ;
_keyboard [ 8 ] . input = IN_KEYBOARD_9 ;
_keyboard [ 9 ] . vKey = ' 9 ' ;
_keyboard [ 9 ] . input = IN_KEYBOARD_0 ;
for ( int i = 0 ; i < NB_KEYBOARD ; i + + )
{
_digital [ _keyboard [ i ] . input ] . mode = OP_DIGITAL_READ ;
}
}
void ProcessInitIO ( )
{
pinMode ( IN_KEYBOARD_1 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_2 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_3 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_4 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_A , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_7 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_8 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_9 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_0 , IO_INPUT | DIGITAL ) ;
pinMode ( IN_KEYBOARD_X , IO_INPUT | DIGITAL ) ;
pinMode ( IN_SENSOR_MIN , IO_INPUT | DIGITAL ) ;
pinMode ( IN_SENSOR_LOW , IO_INPUT | DIGITAL ) ;
pinMode ( IN_SENSOR_HIGH , IO_INPUT | DIGITAL ) ;
pinMode ( IN_SENSOR_MAX , IO_INPUT | DIGITAL ) ;
pinMode ( IN_TANK_LEVEL , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_OUT , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_IN , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_DIF , IO_INPUT | ANALOG ) ;
pinMode ( IN_TANK_MIN , IO_INPUT | ANALOG ) ;
pinMode ( IN_TANK_MAX , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_CAP , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_1 , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_2 , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_3 , IO_INPUT | ANALOG ) ;
pinMode ( IN_FLOW_4 , IO_INPUT | ANALOG ) ;
pinMode ( OUT_PUMP_1 , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_PUMP_2 , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_PUMP_3 , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_PUMP_4 , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_DISPLAY_MODE , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_DISPLAY_GRAFCET , IO_OUTPUT | DIGITAL ) ;
pinMode ( OUT_LEVEL_MIN , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_LEVEL_LOW , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_LEVEL_HIGH , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_LEVEL_MAX , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_FLOW_PER_PUMP , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_FLOW_OUT_AMPLITUDE , IO_OUTPUT | ANALOG ) ;
pinMode ( OUT_BEEP , IO_OUTPUT | DIGITAL ) ;
_digital [ OUT_PUMP_1 ] . error = 30 ;
_digital [ OUT_PUMP_1 ] . efficacite = 1.0 ;
//_digital[OUT_PUMP_1].time = 4294967295; //UINT_MAX
_digital [ OUT_PUMP_2 ] . error = 30 ;
_digital [ OUT_PUMP_2 ] . efficacite = 0.72 ;
//_digital[OUT_PUMP_2].time = 4294967295;
_digital [ OUT_PUMP_3 ] . error = 10 ;
_digital [ OUT_PUMP_3 ] . efficacite = 1.0 ;
//_digital[OUT_PUMP_3].time = 4294967295;
_digital [ OUT_PUMP_4 ] . error = 30 ;
_digital [ OUT_PUMP_4 ] . efficacite = 1.0 ;
//_digital[OUT_PUMP_4].time = 4294967295;
}
void ProcessInitValues ( )
{
t_start = t_backup = millis ( ) ;
srand ( time ( NULL ) ) ;
_digital [ IN_TANK_LEVEL ] . dvalue = _digital [ IN_TANK_MAX ] . dvalue = _digital [ IN_TANK_MIN ] . dvalue = TankInitalValue ;
_digital [ OUT_FLOW_PER_PUMP ] . dvalue = FLOW_PER_PUMP ;
_digital [ OUT_FLOW_OUT_AMPLITUDE ] . dvalue = 100.0 ;
_digital [ OUT_LEVEL_MIN ] . dvalue = LEVEL_MIN ;
_digital [ OUT_LEVEL_LOW ] . dvalue = 6 ;
_digital [ OUT_LEVEL_HIGH ] . dvalue = 7 ;
_digital [ OUT_LEVEL_MAX ] . dvalue = 9.5 ;
_digital [ IN_FLOW_OUT ] . dvalue = 100.0 ;
}
/**
* Fonctionnement des moteurs
*/
2025-12-03 23:20:46 +01:00
double ProcessMoteur ( int i )
2025-11-30 09:48:43 +01:00
{
double vitesse = 1.0 ;
double t = _digital [ i ] . time / 5000.0 ;
if ( _digital [ i ] . ivalue )
{
if ( _digital [ i ] . time < 2500 )
{
vitesse = 4 * pow ( t , 3.0 ) ;
}
else if ( _digital [ i ] . time < 5000 )
{
vitesse = 1.0 - pow ( 2 - 2 * t , 3 ) / 2.0 ;
}
else
{
vitesse = 1.0 + 1.0 / ( _digital [ i ] . error * 2.0 ) - rand ( ) / ( double ) RAND_MAX / _digital [ i ] . error ;
}
}
else
{
if ( _digital [ i ] . time < 2500 )
{
vitesse = 1 - 4 * pow ( t , 3.0 ) ;
}
else if ( _digital [ i ] . time < 5000 )
{
vitesse = pow ( 2 - 2 * t , 3 ) / 2.0 ;
// vitesse = 1 - pow(t, 4.0);
}
else
{
vitesse = 0.0 ;
}
}
return _digital [ OUT_FLOW_PER_PUMP ] . dvalue * _digital [ i ] . efficacite * vitesse ;
}
void ProcessException ( )
{
if ( t_elapsed > 30 ) {
_digital [ OUT_PUMP_1 ] . mode = 0 ;
} else if ( t_elapsed > 15 ) {
_digital [ IN_SENSOR_LOW ] . mode = 0 ;
}
}
void Process ( )
{
// *****
unsigned long t = millis ( ) ;
t_elapsed = ( t - t_start ) / 1000.0 ;
dt = ( t - t_backup ) / 1000.0 ;
// ***** FLOW OUT
if ( _digital [ IN_TANK_LEVEL ] . dvalue > 1.0 )
{
//_digital[IN_FLOW_OUT].dvalue = SimulConsoSinusoidale(t);
_digital [ IN_FLOW_OUT ] . dvalue = SimulConsoBrown ( _digital [ IN_FLOW_OUT ] . dvalue ) ;
}
else
{
if ( _digital [ IN_FLOW_CAP ] . dvalue = = 0.0 ) {
_digital [ IN_FLOW_CAP ] . dvalue = _digital [ IN_FLOW_OUT ] . dvalue ;
}
_digital [ IN_FLOW_OUT ] . dvalue = _digital [ IN_FLOW_CAP ] . dvalue * _digital [ IN_TANK_LEVEL ] . dvalue ;
}
// ***** FLOW IN
_digital [ IN_FLOW_IN ] . dvalue = 0 ;
for ( int i = OUT_PUMP_1 ; i < = OUT_PUMP_4 ; i + + )
{
_digital [ i - 4 ] . dvalue = ProcessMoteur ( i ) ;
_digital [ IN_FLOW_IN ] . dvalue + = _digital [ i - 4 ] . dvalue ;
}
_digital [ IN_FLOW_DIF ] . dvalue = _digital [ IN_FLOW_IN ] . dvalue - _digital [ IN_FLOW_OUT ] . dvalue ;
// ***** TANK LEVEL
_digital [ IN_TANK_LEVEL ] . dvalue + = ( _digital [ IN_FLOW_IN ] . dvalue - _digital [ IN_FLOW_OUT ] . dvalue ) / 1000.0 * dt ;
if ( _digital [ IN_TANK_LEVEL ] . dvalue > 10.0 ) {
_digital [ IN_TANK_LEVEL ] . dvalue = 10.0 ;
}
if ( _digital [ IN_TANK_LEVEL ] . dvalue > _digital [ IN_TANK_MAX ] . dvalue ) {
_digital [ IN_TANK_MAX ] . dvalue = _digital [ IN_TANK_LEVEL ] . dvalue ;
}
if ( _digital [ IN_TANK_LEVEL ] . dvalue < _digital [ IN_TANK_MIN ] . dvalue ) {
_digital [ IN_TANK_MIN ] . dvalue = _digital [ IN_TANK_LEVEL ] . dvalue ;
}
// **** KEYBOARD
if ( _digital [ IN_KEYBOARD_X ] . raising )
{
_digital [ IN_SENSOR_LOW ] . mode = _digital [ IN_SENSOR_LOW ] . mode ^ 0x01 ;
}
for ( int i = IN_KEYBOARD_7 ; i < = IN_KEYBOARD_0 ; i + + )
{
if ( _digital [ i ] . raising )
{
unsigned char p = i + ( OUT_PUMP_1 - IN_KEYBOARD_7 ) ;
_digital [ p ] . mode ^ = 0x01 ;
if ( ! ( _digital [ p ] . mode & 0x01 ) ) {
_digital [ p ] . ivalue = 0 ;
_digital [ p ] . dvalue = 0.0 ;
}
}
}
// **** SENSOR
int test ;
test = ( _digital [ IN_TANK_LEVEL ] . dvalue > _digital [ OUT_LEVEL_MIN ] . dvalue ) ;
if ( _digital [ IN_SENSOR_MIN ] . ivalue ! = test )
{
if ( test = = 0 )
{
_digital [ IN_SENSOR_MIN ] . nb + = 1 ;
}
_digital [ IN_SENSOR_MIN ] . ivalue = test ;
}
test = _digital [ IN_TANK_LEVEL ] . dvalue > _digital [ OUT_LEVEL_LOW ] . dvalue & & _digital [ IN_SENSOR_LOW ] . mode & 0x01 ;
if ( _digital [ IN_SENSOR_LOW ] . ivalue ! = test )
{
if ( test = = 0 )
{
_digital [ IN_SENSOR_LOW ] . nb + = 1 ;
}
_digital [ IN_SENSOR_LOW ] . ivalue = test ;
}
test = _digital [ IN_TANK_LEVEL ] . dvalue > _digital [ OUT_LEVEL_MAX ] . dvalue ;
if ( _digital [ IN_SENSOR_MAX ] . ivalue ! = test )
{
if ( test = = 1 )
{
_digital [ IN_SENSOR_MAX ] . nb + = 1 ;
}
_digital [ IN_SENSOR_MAX ] . ivalue = test ;
}
test = _digital [ IN_TANK_LEVEL ] . dvalue > _digital [ OUT_LEVEL_HIGH ] . dvalue ;
if ( _digital [ IN_SENSOR_HIGH ] . ivalue ! = test )
{
if ( test = = 1 )
{
_digital [ IN_SENSOR_HIGH ] . nb + = 1 ;
}
_digital [ IN_SENSOR_HIGH ] . ivalue = test ;
}
2025-12-03 23:27:56 +01:00
Affichage ( ) ;
2025-11-30 09:48:43 +01:00
t_backup = t ;
}
2025-12-03 23:20:46 +01:00
double SimulConsoSinusoidale ( long t )
2025-11-30 09:48:43 +01:00
{
double alea = ( ( long ) ( t / 100.0 ) % 600 ) * 3 / 1800.0 * PI ;
//mvprintw(18, 0, "%ld %f", (long)(t / 100.0), alea);
return 100 + cos ( alea ) * cos ( alea ) * _digital [ OUT_FLOW_OUT_AMPLITUDE ] . dvalue ;
}
2025-12-03 23:20:46 +01:00
// dt : Intervalle de temps
2025-11-30 09:48:43 +01:00
double SimulConsoBrown ( double valeur_precedente )
{
float mu = 0.01 * - ( ( ( ( int ) t_elapsed / 30 ) % 2 ) * 2 - 1 ) ; // Taux de croissance (1%)
float sigma = 0.05 ; // Volatilité (5%)
mvprintw ( 8 , 40 , " (µ %.1f %% ; σ %.1f %%) " , mu * 100 , sigma * 100 ) ;
// Nombre aléatoire compris dans [-1 +1]
2025-12-03 23:20:46 +01:00
float rand_std_normal = ( ( double ) rand ( ) / RAND_MAX ) * 2.0 - 1.0 ;
2025-11-30 09:48:43 +01:00
// Calcule la variation logarithmique pour cette étape
float drift = ( mu - 0.5f * sigma * sigma ) * dt ;
float diffusion = sigma * sqrt ( dt ) * rand_std_normal ;
return valeur_precedente * exp ( drift + diffusion ) ;
}
/**
* Affichage dans la console
*/
/**
2025-12-03 23:20:46 +01:00
* Initialisation , affichage des parties statiques
2025-11-30 09:48:43 +01:00
*/
void AffichageWindow ( )
{
window = subwin ( stdscr , 19 , 62 , 0 , 0 ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
box ( window , 0 , 0 ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Titre
mvwprintw ( window , 1 , 2 , " Château d'eau (11/2024) " ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// I/O
// Ligne du haut
mvwaddch ( window , 2 , 0 , ACS_LTEE ) ;
mvwhline ( window , 2 , 1 , 0 , 60 ) ;
mvwaddch ( window , 2 , 61 , ACS_RTEE ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Ligne du bas
mvwaddch ( window , 7 , 0 , ACS_LTEE ) ;
mvwhline ( window , 7 , 1 , 0 , 60 ) ;
mvwaddch ( window , 7 , 61 , ACS_RTEE ) ;
// Séparation verticale
mvwaddch ( window , 2 , 18 , ACS_TTEE ) ;
mvwvline ( window , 3 , 18 , 0 , 4 ) ;
mvwaddch ( window , 7 , 18 , ACS_BTEE ) ;
// Input : Boutons poussoirs
mvwprintw ( window , 3 , 2 , " BP 1 " ) ;
mvwprintw ( window , 4 , 2 , " BP 2 " ) ;
mvwprintw ( window , 5 , 2 , " BP 3 " ) ;
mvwprintw ( window , 6 , 2 , " BP 4 " ) ;
// Output : Moteurs pompes
mvwprintw ( window , 3 , 20 , " Pompe 1 " ) ;
mvwprintw ( window , 4 , 20 , " Pompe 2 " ) ;
mvwprintw ( window , 5 , 20 , " Pompe 3 " ) ;
mvwprintw ( window , 6 , 20 , " Pompe 4 " ) ;
// Mesures
mvwprintw ( window , 8 , 2 , " Debit en sortie " ) ;
mvwprintw ( window , 9 , 2 , " Debit en entrée " ) ;
mvwprintw ( window , 10 , 2 , " Volume dans le réservoir " ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Graphe
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Ligne du haut
mvwaddch ( window , 11 , 0 , ACS_LTEE ) ;
mvwhline ( window , 11 , 1 , 0 , 60 ) ;
mvwaddch ( window , 11 , 61 , ACS_RTEE ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Ligne du bas
mvwaddch ( window , 13 , 0 , ACS_LTEE ) ;
mvwhline ( window , 13 , 1 , 0 , 60 ) ;
mvwaddch ( window , 13 , 61 , ACS_RTEE ) ;
// Graduations
for ( int i = 1 ; i < 11 ; i + + ) {
mvwaddch ( window , 11 , 6 * i , ACS_TTEE ) ;
mvwaddch ( window , 13 , 6 * i , ACS_BTEE ) ;
}
mvwaddch ( window , 13 , 2 * 6 , ACS_PLUS ) ;
mvwaddch ( window , 13 , 6 * 6 , ACS_PLUS ) ;
mvwaddch ( window , 13 , 7 * 6 , ACS_PLUS ) ;
mvwaddch ( window , 13 , 57 , ACS_TTEE ) ; //9.5 x 6
mvwvline ( window , 12 , 6 * 10 , 0 , 1 ) ;
// Légende
mvwaddch ( window , 16 , 0 , ACS_LTEE ) ;
mvwhline ( window , 16 , 1 , 0 , 60 ) ;
mvwaddch ( window , 16 , 61 , ACS_RTEE ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
mvwprintw ( window , 14 , 2 * 6 - 1 , " min " ) ;
mvwprintw ( window , 14 , 6 * 6 - 2 , " low " ) ;
mvwprintw ( window , 14 , 7 * 6 , " high " ) ;
mvwprintw ( window , 14 , 56 , " max " ) ;
// Informations
2025-12-03 23:20:46 +01:00
mvwprintw ( window , 17 , 2 , " Mode " ) ;
2025-11-30 09:48:43 +01:00
mvwaddch ( window , 16 , 18 , ACS_TTEE ) ;
mvwaddch ( window , 18 , 18 , ACS_BTEE ) ;
mvwvline ( window , 17 , 18 , 0 , 1 ) ;
mvwprintw ( window , 17 , 20 , " Grafcet " ) ;
mvwaddch ( window , 16 , 31 , ACS_TTEE ) ;
mvwaddch ( window , 18 , 31 , ACS_BTEE ) ;
mvwvline ( window , 17 , 31 , 0 , 1 ) ;
mvwprintw ( window , 17 , 33 , " min " ) ;
mvwprintw ( window , 17 , 46 , " max " ) ;
wrefresh ( window ) ;
}
2025-12-03 23:27:56 +01:00
void Affichage ( )
2025-11-30 09:48:43 +01:00
{
mvwprintw ( window , 1 , 50 , " %5.1f s " , t_elapsed ) ;
for ( int i = OUT_PUMP_1 ; i < = OUT_PUMP_4 ; i + + )
{
mvwprintw ( window , ( short ) ( i - OUT_PUMP_1 + 3 ) , 30 , " %c %5.1f s %dx " , _digital [ i ] . mode & 0x01 ? _digital [ i ] . ivalue ? ' M ' : ' . ' : ' X ' , _digital [ i ] . duration , _digital [ i ] . nb ) ;
}
for ( int i = IN_KEYBOARD_1 ; i < = IN_KEYBOARD_4 ; i + + )
{
mvwprintw ( window , ( short ) ( i + 3 ) , 10 , _digital [ _keyboard [ i ] . input ] . ivalue ? " 1 " : " 0 " ) ;
}
mvwprintw ( window , 8 , 28 , " %3d l/s " , ( int ) _digital [ IN_FLOW_OUT ] . dvalue ) ;
mvwprintw ( window , 9 , 28 , " %3d l/s " , ( int ) _digital [ IN_FLOW_IN ] . dvalue ) ;
mvwprintw ( window , 10 , 29 , " %5.2lf m3 (%+d l/s) " , _digital [ IN_TANK_LEVEL ] . dvalue , ( int ) _digital [ IN_FLOW_DIF ] . dvalue ) ;
AffichageGraphe ( 12 , 1 , _digital [ IN_TANK_LEVEL ] . dvalue * 6 ) ;
/*
if ( _digital [ IN_SENSOR_LOW ] . mode & 0x01 )
{
mvwprintw ( window , 15 , 1 , " (%dx) (%dx) (%dx) (%dx) " , _digital [ IN_SENSOR_MIN ] . nb , _digital [ IN_SENSOR_LOW ] . nb , _digital [ IN_SENSOR_HIGH ] . nb , _digital [ IN_SENSOR_MAX ] . nb ) ;
}
else
{
mvwprintw ( window , 15 , 1 , " (%dx) X (%dx) (%dx) (%dx) " , _digital [ IN_SENSOR_MIN ] . nb , _digital [ IN_SENSOR_LOW ] . nb , _digital [ IN_SENSOR_HIGH ] . nb , _digital [ IN_SENSOR_MAX ] . nb ) ;
}
*/
mvwprintw ( window , 14 , 15 , " %d " , _digital [ IN_SENSOR_MIN ] . ivalue ) ;
mvwprintw ( window , 14 , 38 , " %d " , _digital [ IN_SENSOR_LOW ] . ivalue ) ;
mvwprintw ( window , 14 , 47 , " %d " , _digital [ IN_SENSOR_HIGH ] . ivalue ) ;
mvwprintw ( window , 14 , 60 , " %d " , _digital [ IN_SENSOR_MAX ] . ivalue ) ;
mvwprintw ( window , 15 , 11 , " (%dx) %s " , _digital [ IN_SENSOR_MIN ] . nb , _digital [ IN_SENSOR_MIN ] . mode & 0x01 ? " " : " D " ) ;
mvwprintw ( window , 15 , 34 , " (%dx) %s " , _digital [ IN_SENSOR_LOW ] . nb , _digital [ IN_SENSOR_LOW ] . mode & 0x01 ? " " : " D " ) ;
mvwprintw ( window , 15 , 42 , " (%dx) %s " , _digital [ IN_SENSOR_HIGH ] . nb , _digital [ IN_SENSOR_HIGH ] . mode & 0x01 ? " " : " D " ) ;
mvwprintw ( window , 15 , 56 , " (%dx) " , _digital [ IN_SENSOR_MAX ] . nb ) ;
// Informations complémentaires
mvwprintw ( window , 17 , 2 , _digital [ OUT_DISPLAY_MODE ] . ivalue ? " Automatique " : " Manuel " ) ;
mvwprintw ( window , 17 , 28 , " %d " , _digital [ OUT_DISPLAY_GRAFCET ] . ivalue ) ;
mvwprintw ( window , 17 , 38 , " %4.2lf m3 " , _digital [ IN_TANK_MIN ] . dvalue ) ;
mvwprintw ( window , 17 , 51 , " %4.2lf m3 " , _digital [ IN_TANK_MAX ] . dvalue ) ;
wrefresh ( window ) ;
}
void AffichageGraphe ( int y , int x , double value )
{
int entier = ( int ) ( value ) ;
int i ;
for ( i = 0 ; i < entier ; i + + )
{
2025-12-03 23:20:46 +01:00
mvwaddwstr ( window , y , x + i , L " █ " ) ; // U+2588
2025-11-30 09:48:43 +01:00
}
int frac = ( int ) ( ( value - entier ) * 4 ) ;
if ( frac > 3 ) // 0.75 -> 0.99
{
2025-12-03 23:20:46 +01:00
mvwaddwstr ( window , y , x + i , L " ▊ " ) ; // U+258A
2025-11-30 09:48:43 +01:00
entier + = 1 ;
}
if ( frac > 2 ) // 0.5 -> 0.99
{
2025-12-03 23:20:46 +01:00
mvwaddwstr ( window , y , x + i , L " ▌ " ) ; // U+258C
2025-11-30 09:48:43 +01:00
entier + = 1 ;
}
else if ( frac > 1 ) // 0.25 -> 0.49
{
2025-12-03 23:20:46 +01:00
mvwaddwstr ( window , y , x + i , L " ▎ " ) ; //U+258E
2025-11-30 09:48:43 +01:00
entier + = 1 ;
}
for ( int i = entier ; i < 59 ; i + + )
{
mvwprintw ( window , y , x + i , " " ) ;
2025-12-03 23:20:46 +01:00
}
2025-11-30 09:48:43 +01:00
}
/**
2025-12-03 23:20:46 +01:00
* Prometheus
2025-11-30 09:48:43 +01:00
*/
2025-12-03 23:20:46 +01:00
void InitPrometheus ( )
2025-11-30 09:48:43 +01:00
{
2025-12-03 23:20:46 +01:00
static Exposer exposer { " 0.0.0.0:8099 " } ;
// Le registre central
registry = std : : make_shared < Registry > ( ) ;
exposer . RegisterCollectable ( registry ) ;
// Exemple : gauge (comme votre debit)
auto & gauge_family = BuildGauge ( )
. Name ( " geii_debit " )
. Help ( " Débit en l/s " )
. Register ( * registry ) ;
debit_entree = & gauge_family . Add ( { { " numero " , " entree " } } ) ;
debit_sortie = & gauge_family . Add ( { { " numero " , " sortie " } } ) ;
/*
2025-11-30 09:48:43 +01:00
int result = pcr_init ( 0 , " geii_ " ) ;
std : : array < const char * , 1 > labels = { " numero " } ;
pm_pompe = prom_counter_new ( " pompe_on " , " Mise en marche de la pompe "
, labels . size ( ) , labels . data ( ) ) ;
pcr_register_metric ( pm_pompe ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
pm_debit = prom_gauge_new ( " debit " , " Débit en l/s "
, labels . size ( ) , labels . data ( ) ) ;
pcr_register_metric ( pm_debit ) ;
promhttp_set_active_collector_registry ( NULL ) ;
2025-12-03 23:20:46 +01:00
2025-11-30 09:48:43 +01:00
// Serveur web
server = promhttp_start_daemon ( MHD_USE_SELECT_INTERNALLY
, 8099 , NULL , NULL ) ;
if ( server = = NULL )
{
printf ( " Impossible de démarrer le serveur HTTP \n " ) ;
exit ( 1 ) ;
}
2025-12-03 23:20:46 +01:00
*/
2025-11-30 09:48:43 +01:00
}
void ProcessPrometheus ( )
{
// raising = 1 => front montant sur la sortie
2025-12-03 23:20:46 +01:00
/*
2025-11-30 09:48:43 +01:00
if ( _digital [ OUT_PUMP_1 ] . raising ) {
std : : array < const char * , 1 > labels1 = { " 1 " } ;
prom_counter_inc ( pm_pompe , labels1 . data ( ) ) ;
}
2025-12-03 23:20:46 +01:00
*/
debit_entree - > Set ( _digital [ IN_FLOW_OUT ] . dvalue ) ;
debit_sortie - > Set ( _digital [ IN_FLOW_IN ] . dvalue ) ;
2025-11-30 09:48:43 +01:00
}