2
0
Files
lpsarii/autom.cpp

504 lines
12 KiB
C++
Raw Normal View History

2026-01-09 07:46:52 +01:00
#include <stdio.h>
#include <time.h>
2026-01-09 11:24:51 +01:00
#include <unistd.h>
2026-01-09 07:46:52 +01:00
#undef timeout
#include "mqtt/async_client.h"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
/* From Arduino.h */
#define HIGH 0x1
#define LOW 0x00
#define IO_INPUT 0x02
#define IO_OUTPUT 0x04
#define DIGITAL 0x08
#define ANALOG 0x10
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define true 1
#define false 0
// Temps
// Timestamp unix en millisecondes
// t_start : timestamp de départ
// t_backup : timestamp de la précédente itération
// t_elapsed : temps écoulé en secondes depuis le départ
// dt (delta t) : temps écoulé en secondes depuis la dernière itération
unsigned long t_start, t_backup;
double t_elapsed, dt;
unsigned long millis()
{
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return ((unsigned long)now.tv_sec) * 1000 + ((unsigned long)now.tv_nsec) / 1000000;
}
#define OP_DIGITAL_READ 0
#define OP_DIGITAL_WRITE 1
#define OP_ANALOG_READ 2
#define OP_ANALOG_WRITE 3
#define OP_PIN_MODE 4
2026-01-09 11:24:51 +01:00
int marche = 0;
int arret = 1;
2026-01-14 21:03:56 +01:00
int reset = 0;
2026-01-09 11:24:51 +01:00
int b0, b1, b2, b3, b4, b5, b6, b7;
int i0, i1, i2, i3, i4, i5, i6, i7;
2026-01-12 23:32:48 +01:00
int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11;
2026-01-09 11:44:24 +01:00
int m0, m1, m2, m3;
int v0;
2026-01-14 13:46:18 +01:00
int p0;
2026-01-09 11:24:51 +01:00
2026-01-10 07:29:55 +01:00
int a0, a1, a2, a3, a4, a5, a6, a7;
int c0, c1, c2, c3, c4, c5, c6, c7;
2026-01-14 21:03:56 +01:00
int bouton[8];
int interrupteur[8];
int capteur[8];
int sortie[12];
int moteur[4];
int niveau[4];
int consigne[4];
int actionneur[8];
void process();
2026-01-09 11:24:51 +01:00
/* ********************************************************
* MQTT *
* *
******************************************************** */
2026-01-09 07:46:52 +01:00
2026-01-09 11:24:51 +01:00
/* Configuration MQTT */
const std::string ADDRESS = "tcp://rabbitmq:1883";
const std::string CLIENTID = "CppClientTP";
const std::string TOPIC = "geii/in/#";
const int QOS = 1;
const int CYCLE_MS = 100;
mqtt::async_client client(ADDRESS, CLIENTID);
2026-01-09 07:46:52 +01:00
void mqtt_send(mqtt::async_client *client);
2026-01-09 11:24:51 +01:00
2026-01-09 07:46:52 +01:00
// Réception des messages MQTT
// ************************************************************
class callback : public virtual mqtt::callback
{
2026-01-09 07:46:52 +01:00
public:
2026-01-14 21:03:56 +01:00
void message_arrived(mqtt::const_message_ptr msg) override
{
std::string payload = msg->to_string();
2026-01-09 11:24:51 +01:00
2026-01-14 21:03:56 +01:00
try
{
json j = json::parse(payload);
marche = 0;
arret = 1;
b0 = b1 = b2 = b3 = b4 = b5 = b6 = b7 = 0;
2026-01-09 11:24:51 +01:00
2026-01-14 21:03:56 +01:00
// Ne rien faire si l'objet JSON est vide
if (j.empty())
return;
2026-01-09 11:24:51 +01:00
2026-01-14 21:03:56 +01:00
if (j.contains("marche"))
marche = j["marche"].get<int>() != 0;
2026-01-09 11:24:51 +01:00
2026-01-14 21:03:56 +01:00
if (j.contains("arret"))
arret = j["arret"].get<int>() != 0;
if (j.contains("reset"))
reset = j["reset"].get<int>() != 0;
2026-01-09 11:24:51 +01:00
if (j.contains("b0") && j["b0"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[0] = b0 = j["b0"].get<int>();
}
if (j.contains("b1") && j["b1"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[1] = b1 = j["b1"].get<int>();
}
if (j.contains("b2") && j["b2"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[2] = b2 = j["b2"].get<int>();
}
if (j.contains("b3") && j["b3"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[3] = b3 = j["b3"].get<int>();
}
if (j.contains("b4") && j["b4"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[4] = b4 = j["b4"].get<int>();
}
if (j.contains("b5") && j["b5"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[5] = b5 = j["b5"].get<int>();
}
if (j.contains("b6") && j["b6"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[6] = b6 = j["b6"].get<int>();
}
if (j.contains("b7") && j["b7"].is_number())
2026-01-14 21:03:56 +01:00
{
bouton[7] = b7 = j["b7"].get<int>();
}
if (j.contains("i0"))
interrupteur[0] = i0 = j["i0"].get<int>();
if (j.contains("i1"))
interrupteur[1] = i1 = j["i1"].get<int>();
if (j.contains("i2"))
interrupteur[2] = i2 = j["i2"].get<int>();
if (j.contains("i3"))
interrupteur[3] = i3 = j["i3"].get<int>();
if (j.contains("i4"))
interrupteur[4] = i4 = j["i4"].get<int>();
if (j.contains("i5"))
interrupteur[5] = i5 = j["i5"].get<int>();
if (j.contains("i6"))
interrupteur[6] = i6 = j["i6"].get<int>();
if (j.contains("i7"))
interrupteur[7] = i7 = j["i7"].get<int>();
2026-01-09 11:24:51 +01:00
2026-01-12 18:43:34 +01:00
if (j.contains("c0") && j["c0"].is_number())
2026-01-14 21:03:56 +01:00
capteur[0] = c0 = j["c0"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c1") && j["c1"].is_number())
2026-01-14 21:03:56 +01:00
capteur[1] = c1 = j["c1"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c2") && j["c2"].is_number())
2026-01-14 21:03:56 +01:00
capteur[2] = c2 = j["c2"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c3") && j["c3"].is_number())
2026-01-14 21:03:56 +01:00
capteur[3] = c3 = j["c3"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c4") && j["c4"].is_number())
2026-01-14 21:03:56 +01:00
capteur[4] = c4 = j["c4"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c5") && j["c5"].is_number())
2026-01-14 21:03:56 +01:00
capteur[5] = c5 = j["c5"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c6") && j["c6"].is_number())
2026-01-14 21:03:56 +01:00
capteur[6] = c6 = j["c6"].get<int>();
2026-01-12 18:43:34 +01:00
if (j.contains("c7") && j["c7"].is_number())
2026-01-14 21:03:56 +01:00
capteur[7] = c7 = j["c7"].get<int>();
2026-01-10 07:29:55 +01:00
2026-01-14 07:37:16 +01:00
if (j.contains("v0") && j["v0"].is_number())
2026-01-14 21:03:56 +01:00
v0 = j["v0"].get<int>();
2026-01-14 07:37:16 +01:00
if (j.contains("p0") && j["p0"].is_number())
2026-01-14 13:46:18 +01:00
p0 = j["p0"].get<int>();
2026-01-09 11:44:24 +01:00
process();
mqtt_send(&client);
}
2026-01-14 21:03:56 +01:00
catch (const json::parse_error &e)
{
std::cerr << "Erreur JSON : " << e.what() << "\n";
}
}
2026-01-09 07:46:52 +01:00
};
2026-01-09 11:24:51 +01:00
callback cb;
2026-01-14 21:03:56 +01:00
void mqtt_open(mqtt::async_client *client)
{
2026-01-09 07:46:52 +01:00
2026-01-14 21:03:56 +01:00
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";
}
2026-01-09 07:46:52 +01:00
}
void mqtt_send(mqtt::async_client *client)
{
json obj = {
{"s0", s0},
{"s1", s1},
{"s2", s2},
{"s3", s3},
{"s4", s4},
{"s5", s5},
{"s6", s6},
{"s7", s7},
{"m0", m0},
{"m1", m1},
{"m2", m2},
{"m3", m3},
2026-01-10 07:29:55 +01:00
{"a0", a0},
{"a1", a1},
{"a2", a2},
{"a3", a3},
{"a4", a4},
{"a5", a5},
{"a6", a6},
{"a7", a7},
2026-01-12 23:32:48 +01:00
{"s8", s8},
{"s9", s9},
{"s10", s10},
{"s11", s11},
};
std::string payload = obj.dump();
auto msg = mqtt::make_message("geii/out", payload);
msg->set_qos(1);
client->publish(msg);
}
2026-01-14 21:03:56 +01:00
void mqtt_close()
{
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;
}
2026-01-09 07:46:52 +01:00
}
2026-01-09 11:24:51 +01:00
// ************************************************************
2026-01-09 07:46:52 +01:00
/* ********************************************************
* TEMPORISATION RETARD A LA MONTEE *
* La sortie passe à 1 au bout de la tempo *
******************************************************** */
class TemporisationRetardMontee
{
2026-01-14 21:03:56 +01:00
// methodes
public:
// Contructeur qui prend la duree souhaitee de la temporisation
2026-01-09 07:46:52 +01:00
TemporisationRetardMontee(unsigned long duree)
{
this->duree = duree;
sortie = false;
captureTemps = false;
}
2026-01-14 21:03:56 +01:00
// Activation de la temporisation. Doit etre fait tout le temps de la duree de la tempo
2026-01-09 07:46:52 +01:00
void activation()
{
// Capture du temps de reference
2026-01-14 21:03:56 +01:00
if (!captureTemps)
2026-01-09 07:46:52 +01:00
{
debut = millis();
captureTemps = true;
}
// Calcul du temps ecoule depuis le temps de reference
tempsEcoule = millis() - debut;
// Mise a 1 de la fin de tempo
if (tempsEcoule >= duree)
{
sortie = true;
captureTemps = false;
}
else
{
sortie = false;
}
}
// Precharge de la temporisation
void setDuree(unsigned long majduree)
{
duree = majduree;
sortie = false;
captureTemps = false;
}
// Interrogation du bit de fin de tempo
2026-01-14 21:03:56 +01:00
bool getSortie()
2026-01-09 07:46:52 +01:00
{
2026-01-14 21:03:56 +01:00
return (sortie);
2026-01-09 07:46:52 +01:00
}
// Recuperation du temps ecoule depuis le debut si necessaire
unsigned long getTempsEcoule()
{
2026-01-14 21:03:56 +01:00
return (tempsEcoule);
2026-01-09 07:46:52 +01:00
}
2026-01-14 21:03:56 +01:00
// Attributs
private:
unsigned long duree;
unsigned long debut;
unsigned long tempsEcoule;
bool captureTemps;
bool sortie;
2026-01-09 07:46:52 +01:00
};
/********************************************************
2026-01-14 21:03:56 +01:00
* TEMPORISATION RETARD A LA DESCENTE *
* La sortie passe à 0 au bout de la tempo *
*********************************************************/
2026-01-09 07:46:52 +01:00
class TemporisationRetardDescente
{
2026-01-14 21:03:56 +01:00
public:
// Contructeur qui prend la duree souhaitee de la temporisation
2026-01-09 07:46:52 +01:00
TemporisationRetardDescente(unsigned long duree)
{
this->duree = duree;
sortie = false;
captureTemps = false;
}
2026-01-14 21:03:56 +01:00
// Activation de la temporisation. Doit etre fait tout le temps de la duree de la tempo
2026-01-09 07:46:52 +01:00
void activation()
{
// Capture du temps de reference
2026-01-14 21:03:56 +01:00
if (!captureTemps)
2026-01-09 07:46:52 +01:00
{
debut = millis();
captureTemps = true;
sortie = true;
}
// Calcul du temps ecoule depuis le temps de reference
tempsEcoule = millis() - debut;
// Mise a 0 de la fin de tempo
if (tempsEcoule >= duree)
{
sortie = false;
captureTemps = false;
}
}
// Precharge de la temporisation
void setDuree(unsigned long majduree)
{
duree = majduree;
sortie = false;
captureTemps = false;
}
// Interrogration du bit de fin de tempo
2026-01-14 21:03:56 +01:00
bool getSortie()
2026-01-09 07:46:52 +01:00
{
2026-01-14 21:03:56 +01:00
return (sortie);
2026-01-09 07:46:52 +01:00
}
// Recuperation du temps ecoule depuis le debut si necessaire
2026-01-14 21:03:56 +01:00
unsigned long getTempsEcoule()
2026-01-09 07:46:52 +01:00
{
2026-01-14 21:03:56 +01:00
return (tempsEcoule);
2026-01-09 07:46:52 +01:00
}
2026-01-14 21:03:56 +01:00
private:
unsigned long duree;
unsigned long debut;
unsigned long tempsEcoule;
bool captureTemps;
bool sortie;
2026-01-09 07:46:52 +01:00
};
/********************************************************
**** CLIGNOTEUR *************************************
*********************************************************/
class Clignoteur
{
2026-01-14 21:03:56 +01:00
// methodes
public:
2026-01-09 07:46:52 +01:00
// Construteur qui prend en parametre le temps haut ou bas souhaitee
Clignoteur(int baseDeTemps)
{
this->baseDeTemps = baseDeTemps;
}
// Fonction qui renvoie true si le clignoteur est ├á l'├®tat haut et false s'il est ├á l'├®tat bas
2026-01-14 21:03:56 +01:00
bool statut()
2026-01-09 07:46:52 +01:00
{
return ((millis() / baseDeTemps) % 2 == 1);
}
2026-01-14 21:03:56 +01:00
// Attributs
private:
int baseDeTemps;
2026-01-09 07:46:52 +01:00
};
/********************************************************
**** COMPTEUR *************************************
**** ATTENTION : Il faut gerer le front montant dans le programme
*********************************************************/
class Compteur
{
2026-01-14 21:03:56 +01:00
// methodes
public:
2026-01-09 07:46:52 +01:00
// Constructeur qui prend en parametre la valeur de preselection
Compteur(int valeurPreselection)
{
this->valeurPreselection = valeurPreselection;
valeur = 0;
}
// Incrementation du compteur
void incrementer()
{
valeur++;
}
// Decrementation du compteur
void decrementer()
{
valeur--;
}
// remise a zero du compteur
void remettreAZero()
{
valeur = 0;
}
// recuperation de la valeur courante
int getValeurCourante()
{
2026-01-14 21:03:56 +01:00
return (valeur);
2026-01-09 07:46:52 +01:00
}
// est-ce que la preselection est atteinte (sortie Q compteur Siemens ou Schnieder)
bool getSortie()
{
2026-01-14 21:03:56 +01:00
return (valeur == valeurPreselection);
2026-01-09 07:46:52 +01:00
}
2026-01-14 21:03:56 +01:00
// Attributs
private:
int valeur;
int valeurPreselection;
2026-01-09 07:46:52 +01:00
};
/********************************************************
**** MISE A L'ECHELLE DE VALEUR ************************
*********************************************************/
class MiseAEchelle
{
2026-01-14 21:03:56 +01:00
public:
2026-01-09 07:46:52 +01:00
// Constructeur qui ne prend en parametre la plage d'entree et la plage de sortie
2026-01-14 21:03:56 +01:00
MiseAEchelle(float minEntree, float maxEntree, float minSortie, float maxSortie)
2026-01-09 07:46:52 +01:00
{
this->minEntree = minEntree;
this->maxEntree = maxEntree;
this->minSortie = minSortie;
this->maxSortie = maxSortie;
}
// fonction de conversion qui prend la valeur a convertir et renvoie la valeur convertie
float convertir(float valeurAConvertir)
{
2026-01-14 21:03:56 +01:00
if (valeurAConvertir >= minEntree && valeurAConvertir <= maxEntree)
2026-01-09 07:46:52 +01:00
{
float norm = (1 / (maxEntree - minEntree)) * (valeurAConvertir - minEntree);
float scale = (maxSortie - minSortie) * norm + minSortie;
2026-01-14 21:03:56 +01:00
return (scale);
2026-01-09 07:46:52 +01:00
}
2026-01-14 21:03:56 +01:00
return (-1000);
2026-01-09 07:46:52 +01:00
}
2026-01-14 21:03:56 +01:00
// Attributs
private:
float minEntree;
float minSortie;
float maxEntree;
2026-01-09 07:46:52 +01:00
float maxSortie;
};