Endpoints batteries : GET /elements/familles et GET /elements avec type=batterie

This commit is contained in:
2026-08-14 11:50:20 +02:00
parent 930a8c300a
commit f5ceca6abb
+131 -68
View File
@@ -25,6 +25,7 @@
// Types de familles (cf TB_Familles.Type_source / TB_Events.Type_source) :
static const int TYPE_SOURCE_CIRCUIT = 1;
static const int TYPE_SOURCE_BATTERIE = 4;
// États circuit (cf commentaire colonne TB_Circuits.Etat dans le schéma) :
static const int ETAT_CIRCUIT_OK = 0;
@@ -48,6 +49,10 @@ static QHttpServerResponse withCors(QHttpServerResponse &&resp)
{
QHttpHeaders headers = resp.headers();
headers.append(QHttpHeaders::WellKnownHeader::AccessControlAllowOrigin, "*");
// Empêche le navigateur de mettre en cache les réponses - sans ça, des
// requêtes identiques répétées (rafraîchissement périodique) pourraient
// recevoir une réponse mise en cache plutôt que la valeur réellement à
// jour en base.
headers.append(QHttpHeaders::WellKnownHeader::CacheControl, "no-store");
resp.setHeaders(std::move(headers));
return std::move(resp);
@@ -88,50 +93,77 @@ int main(int argc, char *argv[])
QUrlQuery query(request.query());
const QString type = query.queryItemValue("type");
if (type != "circuit") {
int typeSource;
if (type == "circuit") typeSource = TYPE_SOURCE_CIRCUIT;
else if (type == "batterie") typeSource = TYPE_SOURCE_BATTERIE;
else {
QJsonObject err;
err["status"] = "erreur";
err["message"] = "type non supporté (seul 'circuit' est implémenté à ce stade)";
err["message"] = "type non supporté (circuit, batterie)";
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::NotImplemented));
}
QJsonArray familles;
QSqlQuery q1(QString("SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=%1 ORDER BY Priorite_affichage").arg(TYPE_SOURCE_CIRCUIT));
QSqlQuery q1(QString("SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=%1 ORDER BY Priorite_affichage").arg(typeSource));
while (q1.next()) {
const int idFamille = q1.value(0).toInt();
const QString nom = q1.value(1).toString();
int etat = 0;
// Alarmes (Events) liées à cette famille :
QSqlQuery q2;
q2.prepare("SELECT COUNT(*) FROM TB_Events WHERE Type_source=:type AND Validite=1 AND Alarme_source>0 "
"AND Etat_test=1 AND ID_Source IN (SELECT Cle_primaire FROM TB_Circuits WHERE ID_Famille=:famille)");
q2.bindValue(":type", TYPE_SOURCE_CIRCUIT);
q2.bindValue(":famille", idFamille);
q2.exec();
if (q2.next() && q2.value(0).toInt() > 0) etat = 1;
if (type == "circuit") {
// Alarmes (Events) liées à cette famille :
QSqlQuery q2;
q2.prepare("SELECT COUNT(*) FROM TB_Events WHERE Type_source=:type AND Validite=1 AND Alarme_source>0 "
"AND Etat_test=1 AND ID_Source IN (SELECT Cle_primaire FROM TB_Circuits WHERE ID_Famille=:famille)");
q2.bindValue(":type", typeSource);
q2.bindValue(":famille", idFamille);
q2.exec();
if (q2.next() && q2.value(0).toInt() > 0) etat = 1;
// État agrégé des circuits de la famille :
QSqlQuery q3;
q3.prepare("SELECT Etat, Etat_commande_carte, Etat_systeme FROM TB_Circuits "
"WHERE ID_Famille=:famille AND Priorite_affichage_accueil>0");
q3.bindValue(":famille", idFamille);
q3.exec();
while (q3.next()) {
const int etatCircuit = q3.value(0).toInt();
const int etatCommandeCarte = q3.value(1).toInt();
const int etatSysteme = q3.value(2).toInt();
// État agrégé des circuits de la famille :
QSqlQuery q3;
q3.prepare("SELECT Etat, Etat_commande_carte, Etat_systeme FROM TB_Circuits "
"WHERE ID_Famille=:famille AND Priorite_affichage_accueil>0");
q3.bindValue(":famille", idFamille);
q3.exec();
while (q3.next()) {
const int etatCircuit = q3.value(0).toInt();
const int etatCommandeCarte = q3.value(1).toInt();
const int etatSysteme = q3.value(2).toInt();
if (etatSysteme != 0
|| etatCircuit == ETAT_CIRCUIT_LIMITATION
|| etatCircuit == ETAT_CIRCUIT_PROTECTION
|| etatCircuit == ETAT_CIRCUIT_DISJONCTE
|| etatCircuit == ETAT_CIRCUIT_ABSENCE_TERRE
|| etatCircuit == ETAT_CIRCUIT_ABSENCE_MASSE) {
etat = 2;
} else if (etat < 2 && (etatCommandeCarte != ETAT_COMMANDE_CARTE_OK || etatCircuit != ETAT_CIRCUIT_OK)) {
etat = 1;
if (etatSysteme != 0
|| etatCircuit == ETAT_CIRCUIT_LIMITATION
|| etatCircuit == ETAT_CIRCUIT_PROTECTION
|| etatCircuit == ETAT_CIRCUIT_DISJONCTE
|| etatCircuit == ETAT_CIRCUIT_ABSENCE_TERRE
|| etatCircuit == ETAT_CIRCUIT_ABSENCE_MASSE) {
etat = 2;
} else if (etat < 2 && (etatCommandeCarte != ETAT_COMMANDE_CARTE_OK || etatCircuit != ETAT_CIRCUIT_OK)) {
etat = 1;
}
}
} else if (type == "batterie") {
// Règle plus simple que les circuits (cf §20.4/§21.8 synthèse) :
// rouge si Etat_systeme en défaut sur une batterie de la famille,
// sinon orange si au moins une alarme (Events), sinon vert.
// Alarmes (Events) liées à cette famille :
QSqlQuery q2;
q2.prepare("SELECT COUNT(*) FROM TB_Events WHERE Type_source=:type AND Validite=1 AND Alarme_source>0 "
"AND Etat_test=1 AND ID_Source IN (SELECT Cle_primaire FROM TB_Batteries WHERE ID_Famille=:famille)");
q2.bindValue(":type", typeSource);
q2.bindValue(":famille", idFamille);
q2.exec();
if (q2.next() && q2.value(0).toInt() > 0) etat = 1;
// Etat_systeme des batteries de la famille :
QSqlQuery q3;
q3.prepare("SELECT Etat_systeme FROM TB_Batteries WHERE ID_Famille=:famille AND Priorite_affichage_accueil>0");
q3.bindValue(":famille", idFamille);
q3.exec();
while (q3.next()) {
if (q3.value(0).toInt() != 0) etat = 2;
}
}
@@ -160,10 +192,10 @@ int main(int argc, char *argv[])
const QString type = query.queryItemValue("type");
const QString familleStr = query.queryItemValue("famille");
if (type != "circuit") {
if (type != "circuit" && type != "batterie") {
QJsonObject err;
err["status"] = "erreur";
err["message"] = "type non supporté (seul 'circuit' est implémenté à ce stade)";
err["message"] = "type non supporté (circuit, batterie)";
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::NotImplemented));
}
@@ -177,43 +209,74 @@ int main(int argc, char *argv[])
}
QJsonArray elements;
QSqlQuery q;
q.prepare(
"SELECT Cle_primaire, Etat_systeme, Nom, Etat_commande_carte, Mode_commande, Etat, Consigne, Old_consigne, "
"Mode_test, Tension, Intensite, Frequence, "
"(SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=TB_Circuits.Adresse_module) AS type_circuit, "
"No_circuit, "
"(SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Visibilite=1 AND "
"(Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,'/%') OR Action_circuits LIKE CONCAT('%;', TB_Circuits.Cle_primaire,'/%'))) AS nb_events, "
"Validation_cdes_events, "
"(SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=:type AND Alarme_source>0 AND Etat_test=1 "
"AND ID_Source=TB_Circuits.Cle_primaire) AS Nb_alarmes "
"FROM TB_Circuits WHERE Priorite_affichage_accueil>0 AND ID_Famille=:famille "
"ORDER BY Priorite_affichage_accueil, Cle_primaire"
);
q.bindValue(":type", TYPE_SOURCE_CIRCUIT);
q.bindValue(":famille", idFamille);
q.exec();
while (q.next()) {
QJsonObject obj;
obj["id"] = q.value(0).toInt();
obj["etat_systeme"] = q.value(1).toInt();
obj["nom"] = q.value(2).toString();
obj["etat_commande_carte"] = q.value(3).toInt();
obj["mode_commande"] = q.value(4).toInt();
obj["etat"] = q.value(5).toInt();
obj["consigne"] = q.value(6).toInt();
obj["old_consigne"] = q.value(7).toInt();
obj["mode_test"] = q.value(8).toInt();
obj["tension"] = q.value(9).toDouble();
obj["intensite"] = q.value(10).toDouble();
obj["frequence"] = q.value(11).toDouble();
obj["type_circuit"] = q.value(12).toInt();
obj["no_circuit"] = q.value(13).toInt();
obj["validation_cdes_events"] = (q.value(14).toInt() == 0) ? -1 : q.value(15).toInt();
obj["etat_events"] = q.value(16).toInt();
elements.append(obj);
if (type == "circuit") {
QSqlQuery q;
q.prepare(
"SELECT Cle_primaire, Etat_systeme, Nom, Etat_commande_carte, Mode_commande, Etat, Consigne, Old_consigne, "
"Mode_test, Tension, Intensite, Frequence, "
"(SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=TB_Circuits.Adresse_module) AS type_circuit, "
"No_circuit, "
"(SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Visibilite=1 AND "
"(Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,'/%') OR Action_circuits LIKE CONCAT('%;', TB_Circuits.Cle_primaire,'/%'))) AS nb_events, "
"Validation_cdes_events, "
"(SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=:type AND Alarme_source>0 AND Etat_test=1 "
"AND ID_Source=TB_Circuits.Cle_primaire) AS Nb_alarmes "
"FROM TB_Circuits WHERE Priorite_affichage_accueil>0 AND ID_Famille=:famille "
"ORDER BY Priorite_affichage_accueil, Cle_primaire"
);
q.bindValue(":type", TYPE_SOURCE_CIRCUIT);
q.bindValue(":famille", idFamille);
q.exec();
while (q.next()) {
QJsonObject obj;
obj["id"] = q.value(0).toInt();
obj["etat_systeme"] = q.value(1).toInt();
obj["nom"] = q.value(2).toString();
obj["etat_commande_carte"] = q.value(3).toInt();
obj["mode_commande"] = q.value(4).toInt();
obj["etat"] = q.value(5).toInt();
obj["consigne"] = q.value(6).toInt();
obj["old_consigne"] = q.value(7).toInt();
obj["mode_test"] = q.value(8).toInt();
obj["tension"] = q.value(9).toDouble();
obj["intensite"] = q.value(10).toDouble();
obj["frequence"] = q.value(11).toDouble();
obj["type_circuit"] = q.value(12).toInt();
obj["no_circuit"] = q.value(13).toInt();
obj["validation_cdes_events"] = (q.value(14).toInt() == 0) ? -1 : q.value(15).toInt();
obj["etat_events"] = q.value(16).toInt();
elements.append(obj);
}
} else if (type == "batterie") {
// Rappel : le champ "etat" retourné ici est le NOMBRE D'ALARMES,
// pas un code d'état comme pour les circuits - fidèle au modèle
// natif existant (modele_batteries), pas une incohérence introduite ici.
QSqlQuery q;
q.prepare(
"SELECT Cle_primaire, Etat_systeme, Nom, Type, Soc, Tension, Tension_nominale, "
"(SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=:type AND Alarme_source>0 AND Etat_test=1 "
"AND ID_Source=TB_Batteries.Cle_primaire) AS Nb_alarmes "
"FROM TB_Batteries WHERE ID_Famille=:famille "
"ORDER BY Priorite_affichage_accueil"
);
q.bindValue(":type", TYPE_SOURCE_BATTERIE);
q.bindValue(":famille", idFamille);
q.exec();
while (q.next()) {
QJsonObject obj;
obj["id"] = q.value(0).toInt();
obj["etat_systeme"] = q.value(1).toInt();
obj["nom"] = q.value(2).toString();
obj["type_batterie"] = q.value(3).toInt();
obj["niveau"] = q.value(4).toDouble();
obj["tension"] = q.value(5).toDouble();
obj["tension_nominale"] = q.value(6).toDouble();
obj["etat"] = q.value(7).toInt();
elements.append(obj);
}
}
QJsonObject reponse;