Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0b1cf97e2 | |||
| 99c7ccac16 | |||
| 430eeca9eb | |||
| 50a3a765d2 |
@@ -1,5 +1,14 @@
|
||||
FROM debian:stable-slim
|
||||
|
||||
ARG USERNAME=vscode
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=1000
|
||||
|
||||
RUN groupadd --gid $USER_GID $USERNAME \
|
||||
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
|
||||
&& apt-get update && apt-get install -y sudo \
|
||||
&& echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
|
||||
RUN RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y \
|
||||
@@ -15,20 +24,32 @@ RUN set -eux; \
|
||||
libmicrohttpd-dev \
|
||||
libcurl4-openssl-dev \
|
||||
zlib1g-dev \
|
||||
prometheus-cpp-dev
|
||||
prometheus-cpp-dev \
|
||||
nlohmann-json3-dev
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y \
|
||||
libpaho-mqtt-dev
|
||||
|
||||
RUN set -eux; \
|
||||
RUN set -eux; \
|
||||
git clone https://github.com/eclipse/paho.mqtt.cpp.git; \
|
||||
cd paho.mqtt.cpp; \
|
||||
git submodule init; \
|
||||
git submodule update; \
|
||||
mkdir build && cd build; \
|
||||
cmake -DPAHO_WITH_MQTT_C=ON ..; \
|
||||
cmake --build . --target install; \
|
||||
ldconfig;
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y \
|
||||
librabbitmq4 \
|
||||
librabbitmq-dev;\
|
||||
apt-get clean
|
||||
|
||||
WORKDIR /root
|
||||
USER $USERNAME
|
||||
WORKDIR /workspace
|
||||
|
||||
CMD ["sleep infinity"]
|
||||
|
||||
54
.devcontainer/compose.yml
Normal file
54
.devcontainer/compose.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
services:
|
||||
dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ..:/workspace:cached
|
||||
command: sleep infinity
|
||||
networks:
|
||||
- dev_net
|
||||
|
||||
nodered:
|
||||
image: nodered/node-red:4.1
|
||||
container_name: nodered
|
||||
ports:
|
||||
- "1880:1880"
|
||||
networks:
|
||||
- dev_net
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
volumes:
|
||||
- ./nodered-data:/data
|
||||
- ./nodered-flows/flows.json:/data/flows.json
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:4.1.4-management
|
||||
container_name: rabbitmq
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: "admin"
|
||||
RABBITMQ_DEFAULT_PASS: "geii2025"
|
||||
|
||||
# Activation MQTT sur le port 1883
|
||||
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS: >
|
||||
-rabbitmq_mqtt tcp_listeners [1883]
|
||||
|
||||
ports:
|
||||
- "5672:5672" # AMQP
|
||||
- "1883:1883" # MQTT
|
||||
- "15672:15672" # RabbitMQ Manager
|
||||
networks:
|
||||
- dev_net
|
||||
volumes:
|
||||
- rabbitmq:/var/lib/rabbitmq
|
||||
|
||||
# Activation des plugins + démarrage serveur
|
||||
command: >
|
||||
sh -c "rabbitmq-plugins enable --offline rabbitmq_mqtt rabbitmq_management &&
|
||||
rabbitmq-server"
|
||||
|
||||
networks:
|
||||
dev_net:
|
||||
|
||||
volumes:
|
||||
rabbitmq:
|
||||
@@ -1,13 +1,10 @@
|
||||
{
|
||||
"name": "Developpement C",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"runArgs": [
|
||||
"--label", "prometheus=true",
|
||||
"--network=tp_net",
|
||||
"--name=pompes"
|
||||
"dockerComposeFile": [
|
||||
"compose.yml"
|
||||
],
|
||||
"service": "dev",
|
||||
"workspaceFolder": "/workspace",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
|
||||
@@ -323,7 +323,7 @@ class MiseAEchelle
|
||||
float minEntree;
|
||||
float minSortie;
|
||||
float maxEntree;
|
||||
float maxSortie;
|
||||
float maxSortie;
|
||||
};
|
||||
|
||||
/* READ */
|
||||
@@ -409,19 +409,3 @@ void analogWrite(unsigned int p, double value)
|
||||
|
||||
_digital[p].dvalue = value;
|
||||
}
|
||||
|
||||
/* ********************************************************
|
||||
* Console *
|
||||
* *
|
||||
******************************************************** */
|
||||
void ConsoleInit()
|
||||
{
|
||||
setlocale(LC_ALL, ""); // Activer le support des caractères Unicode
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
initscr(); // Initialise ncurses
|
||||
raw(); // Mode brut, sans besoin de validation par Entrée
|
||||
keypad(stdscr, TRUE); // Active les touches spéciales comme ESC
|
||||
nodelay(stdscr, TRUE); // Mode non-bloquant pour getch()
|
||||
noecho(); // Ne pas afficher les touches appuyées
|
||||
curs_set(0); // Masquer le curseur
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ find_library(NCURSESW_LIB ncursesw REQUIRED)
|
||||
find_library(RABBITMQ_LIB rabbitmq REQUIRED)
|
||||
|
||||
# Paho MQTT C client
|
||||
find_library(PAHO_MQTTPP3_LIB paho-mqttpp3 REQUIRED)
|
||||
find_library(PAHO_MQTT3C_LIB paho-mqtt3c REQUIRED)
|
||||
|
||||
# -------------------------------
|
||||
@@ -53,5 +54,6 @@ target_link_libraries(geii_exporter
|
||||
${Z_LIB}
|
||||
${NCURSESW_LIB}
|
||||
${RABBITMQ_LIB}
|
||||
${PAHO_MQTT3C_LIB}
|
||||
${PAHO_MQTT3C_LIB} # dépendance C
|
||||
${PAHO_MQTTPP3_LIB} # lib C++
|
||||
)
|
||||
|
||||
583
main.cpp
583
main.cpp
@@ -1,18 +1,48 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ncurses.h>
|
||||
#include <math.h>
|
||||
#include <locale.h>
|
||||
#include <array>
|
||||
#include "main.hpp"
|
||||
#include "AutomForArduino.cpp"
|
||||
|
||||
#include <prometheus/counter.h>
|
||||
#include <prometheus/gauge.h>
|
||||
#include <prometheus/histogram.h>
|
||||
#include <prometheus/registry.h>
|
||||
#include <prometheus/exposer.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <csignal>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#undef timeout
|
||||
#include "mqtt/async_client.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
// Constantes de fonctionnement
|
||||
#define LEVEL_MIN 2
|
||||
#define FLOW_PER_PUMP 150
|
||||
|
||||
WINDOW *window;
|
||||
/* Configuration MQTT */
|
||||
const std::string ADDRESS = "tcp://rabbitmq:1883";
|
||||
const std::string CLIENTID = "CppClientTP";
|
||||
const std::string TOPIC = "geii/ordre/#";
|
||||
const int QOS = 1;
|
||||
const int CYCLE_MS = 100;
|
||||
|
||||
int etape = 10; // Étape du grafcet : début Automatique
|
||||
int etape = 0; // É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;
|
||||
@@ -20,308 +50,89 @@ 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
|
||||
// Réception des messages MQTT
|
||||
// ************************************************************
|
||||
class callback : public virtual mqtt::callback {
|
||||
public:
|
||||
void message_arrived(mqtt::const_message_ptr msg) override {
|
||||
std::string payload = msg->to_string();
|
||||
|
||||
if (payload == "p1") {
|
||||
pompe1 = !pompe1;
|
||||
} else if (payload == "p2") {
|
||||
pompe2 = !pompe2;
|
||||
} else if (payload == "p3") {
|
||||
pompe3 = !pompe3;
|
||||
} else if (payload == "p4") {
|
||||
pompe4 = !pompe4;
|
||||
}
|
||||
}
|
||||
};
|
||||
// ************************************************************
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Initialisation */
|
||||
ConsoleInit();
|
||||
AffichageWindow();
|
||||
|
||||
InitPrometheus();
|
||||
ProcessInitKeyboard();
|
||||
|
||||
ProcessInitIO();
|
||||
ProcessInitValues();
|
||||
|
||||
mqtt::async_client client(ADDRESS, CLIENTID);
|
||||
callback cb;
|
||||
client.set_callback(cb);
|
||||
|
||||
mqtt::connect_options connOpts;
|
||||
connOpts.set_clean_session(true);
|
||||
connOpts.set_user_name("admin");
|
||||
connOpts.set_password("geii2025");
|
||||
try {
|
||||
client.connect(connOpts)->wait();
|
||||
client.start_consuming();
|
||||
client.subscribe(TOPIC, QOS)->wait();
|
||||
} catch (const mqtt::exception &exc) {
|
||||
std::cerr << "Erreur MQTT: " << exc.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int ch = getch(); // Lit l'entrée du clavier sans bloquer
|
||||
|
||||
// **** Break loop if escape key (27) is pressed
|
||||
if (ch == 27 || _digital[OUT_END].ivalue) {
|
||||
break;
|
||||
}
|
||||
|
||||
// **** Beep
|
||||
if (_digital[OUT_BEEP].ivalue)
|
||||
{
|
||||
beep();
|
||||
_digital[OUT_BEEP].ivalue = false;
|
||||
}
|
||||
|
||||
Process();
|
||||
|
||||
LireClavier(ch);
|
||||
LireEntree();
|
||||
EvolutionGrafcet();
|
||||
Actions();
|
||||
sensor_min = digitalRead(IN_SENSOR_MIN);
|
||||
sensor_low = digitalRead(IN_SENSOR_LOW);
|
||||
sensor_high = digitalRead(IN_SENSOR_HIGH);
|
||||
sensor_max = digitalRead(IN_SENSOR_MAX);
|
||||
|
||||
digitalWrite(OUT_PUMP_1, (pompe1 == 1));
|
||||
digitalWrite(OUT_PUMP_2, (pompe2 == 1));
|
||||
digitalWrite(OUT_PUMP_3, (pompe3 == 1));
|
||||
digitalWrite(OUT_PUMP_4, (pompe4 == 1));
|
||||
|
||||
ProcessPrometheus();
|
||||
|
||||
ProcessMQTT(&client);
|
||||
ProcessException();
|
||||
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
endwin(); // Termine ncurses et rétablit le terminal
|
||||
puts("Fin du programme");
|
||||
try {
|
||||
client.unsubscribe(TOPIC)->wait();
|
||||
client.stop_consuming();
|
||||
client.disconnect()->wait();
|
||||
} catch(const mqtt::exception &exc){
|
||||
std::cerr << "Erreur déconnexion MQTT: " << exc.what() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Fin du programme" << std::endl;
|
||||
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);
|
||||
@@ -489,25 +300,6 @@ void Process()
|
||||
_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;
|
||||
|
||||
@@ -551,8 +343,6 @@ void Process()
|
||||
_digital[IN_SENSOR_HIGH].ivalue = test;
|
||||
}
|
||||
|
||||
Affichage();
|
||||
|
||||
t_backup = t;
|
||||
}
|
||||
|
||||
@@ -569,8 +359,6 @@ 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]
|
||||
float rand_std_normal = ((double)rand() / RAND_MAX) * 2.0 - 1.0;
|
||||
|
||||
@@ -585,185 +373,6 @@ double SimulConsoBrown(double valeur_precedente)
|
||||
* Affichage dans la console
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialisation, affichage des parties statiques
|
||||
*/
|
||||
void AffichageWindow()
|
||||
{
|
||||
window = subwin(stdscr, 19, 62, 0, 0);
|
||||
|
||||
box(window, 0, 0);
|
||||
|
||||
// Titre
|
||||
mvwprintw(window, 1, 2, "Château d'eau (11/2024)");
|
||||
|
||||
// I/O
|
||||
// Ligne du haut
|
||||
mvwaddch(window, 2, 0, ACS_LTEE);
|
||||
mvwhline(window, 2, 1, 0, 60);
|
||||
mvwaddch(window, 2, 61, ACS_RTEE);
|
||||
|
||||
// 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");
|
||||
|
||||
// Graphe
|
||||
|
||||
// Ligne du haut
|
||||
mvwaddch(window, 11, 0, ACS_LTEE);
|
||||
mvwhline(window, 11, 1, 0, 60);
|
||||
mvwaddch(window, 11, 61, ACS_RTEE);
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
mvwprintw(window, 17, 2, "Mode");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void Affichage()
|
||||
{
|
||||
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++)
|
||||
{
|
||||
mvwaddwstr(window, y, x + i, L"█"); // U+2588
|
||||
}
|
||||
|
||||
int frac = (int)((value - entier) * 4);
|
||||
if (frac > 3) // 0.75 -> 0.99
|
||||
{
|
||||
mvwaddwstr(window, y, x + i, L"▊"); // U+258A
|
||||
entier += 1;
|
||||
}
|
||||
if (frac > 2) // 0.5 -> 0.99
|
||||
{
|
||||
mvwaddwstr(window, y, x + i, L"▌"); // U+258C
|
||||
entier += 1;
|
||||
}
|
||||
else if (frac > 1) // 0.25 -> 0.49
|
||||
{
|
||||
mvwaddwstr(window, y, x + i, L"▎"); //U+258E
|
||||
entier += 1;
|
||||
}
|
||||
|
||||
for (int i = entier; i < 59; i++)
|
||||
{
|
||||
mvwprintw(window, y, x + i, " ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prometheus
|
||||
@@ -778,3 +387,25 @@ void ProcessPrometheus()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ProcessMQTT(mqtt::async_client* client)
|
||||
{
|
||||
json obj = {
|
||||
{"entree", _digital[IN_FLOW_IN].dvalue},
|
||||
{"sortie", _digital[IN_FLOW_OUT].dvalue},
|
||||
{"tank", _digital[IN_TANK_LEVEL].dvalue},
|
||||
{"pompe1", _digital[IN_FLOW_1].dvalue},
|
||||
{"pompe2", _digital[IN_FLOW_2].dvalue},
|
||||
{"pompe3", _digital[IN_FLOW_3].dvalue},
|
||||
{"pompe4", _digital[IN_FLOW_4].dvalue},
|
||||
{"min", _digital[IN_SENSOR_MIN].ivalue},
|
||||
{"low", _digital[IN_SENSOR_LOW].ivalue},
|
||||
{"high", _digital[IN_SENSOR_HIGH].ivalue},
|
||||
{"max", _digital[IN_SENSOR_MAX].ivalue},
|
||||
};
|
||||
|
||||
std::string payload = obj.dump();
|
||||
auto msg = mqtt::make_message("geii/telemetry", payload);
|
||||
msg->set_qos(1);
|
||||
client->publish(msg);
|
||||
}
|
||||
|
||||
28
main.hpp
28
main.hpp
@@ -1,12 +1,8 @@
|
||||
void ConsoleInit();
|
||||
#undef timeout
|
||||
#include "mqtt/async_client.h"
|
||||
|
||||
void LireClavier(int ch);
|
||||
void LireEntree();
|
||||
void EvolutionGrafcet();
|
||||
void Actions();
|
||||
void RemiseZeroInput();
|
||||
|
||||
void ProcessInitKeyboard();
|
||||
void ProcessInitIO();
|
||||
void ProcessInitValues();
|
||||
double ProcessMoteur(int i);
|
||||
@@ -16,27 +12,11 @@ void Process();
|
||||
void InitPrometheus();
|
||||
void ProcessPrometheus();
|
||||
|
||||
void ProcessMQTT(mqtt::async_client* client);
|
||||
|
||||
double SimulConsoSinusoidale(long t);
|
||||
double SimulConsoBrown(double valeur_precedente);
|
||||
|
||||
void AffichageWindow();
|
||||
void Affichage();
|
||||
void AffichageGraphe(int y, int x, double value);
|
||||
|
||||
// KEYBOARD INPUT
|
||||
|
||||
#define IN_KEYBOARD_1 0
|
||||
#define IN_KEYBOARD_2 1
|
||||
#define IN_KEYBOARD_3 2
|
||||
#define IN_KEYBOARD_4 3
|
||||
#define IN_KEYBOARD_A 4
|
||||
|
||||
#define IN_KEYBOARD_X 5
|
||||
#define IN_KEYBOARD_7 6
|
||||
#define IN_KEYBOARD_8 7
|
||||
#define IN_KEYBOARD_9 8
|
||||
#define IN_KEYBOARD_0 9
|
||||
|
||||
// DIGITAL INPUT
|
||||
|
||||
#define IN_SENSOR_MIN 10
|
||||
|
||||
1378
nodered-flows/flows.json
Normal file
1378
nodered-flows/flows.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user