From f5ceca6abb27e11434483df4190557ebac2e4429 Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 14 Aug 2026 11:50:20 +0200 Subject: [PATCH] Endpoints batteries : GET /elements/familles et GET /elements avec type=batterie --- main.cpp | 199 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 131 insertions(+), 68 deletions(-) diff --git a/main.cpp b/main.cpp index d7d4342..4d36e6e 100644 --- a/main.cpp +++ b/main.cpp @@ -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;