Ajouts relatifs aux remontées d'alarmes vers ship2net

This commit is contained in:
2026-10-07 12:07:52 +02:00
parent e4736f2469
commit 7ab27dd9ac
7 changed files with 108 additions and 2 deletions
+1 -1
View File
@@ -1 +1 @@
261006_091623
261007_091503
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef _VERSION_H
#define _VERSION_H
#define VERSION "261006_091623"
#define VERSION "261007_091503"
#endif // _VERSION_H
+106
View File
@@ -1289,6 +1289,112 @@ int main(int argc, char *argv[])
return withCors(QHttpServerResponse(QJsonDocument(reponse).toJson()));
});
// ------------------------------------------------------------------
// GET /alertes?depuis=AAAA-MM-JJ HH:MM:SS - déclenchements et fins des
// events d'ALERTE (Alarme_email ou Alarme_sms actif) enregistrés dans
// TB_Historique depuis cette date incluse (synthèse §51, lot Alertes).
// Appelée par le VPS via NetBird (port 8080) après un coup de sonnette.
// Dates en UTC. "depuis" inclus : deux enregistrements dans la même
// seconde ne sont jamais manqués - le VPS écarte les doublons.
// Au plus 1000 lignes, les plus anciennes d'abord (le VPS avance son
// curseur et relit la suite au passage suivant).
// Comme les autres routes /archives, réservée au VPS : bloquée dans le
// relais /api du nginx du CM5 (location ^~ /api/alertes).
// ------------------------------------------------------------------
server.route("/alertes", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
assurer_connexion_bdd();
QUrlQuery query(request.query());
const QString depuis = query.queryItemValue("depuis", QUrl::FullyDecoded);
static const QRegularExpression format_date(QStringLiteral("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$"));
if (!format_date.match(depuis).hasMatch()) {
QJsonObject err;
err["status"] = "error";
err["message"] = "paramètre depuis attendu au format AAAA-MM-JJ HH:MM:SS (UTC)";
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::BadRequest));
}
// TB_Historique.Date est un TIMESTAMP : lecture forcée en UTC, quel que
// soit le fuseau par défaut du serveur MariaDB.
QSqlQuery fuseau;
fuseau.exec("SET time_zone = '+00:00'");
QSqlQuery q;
q.prepare("SELECT DATE_FORMAT(H.Date, '%Y-%m-%d %H:%i:%s'), H.Type, H.ID_Source, E.Nom,"
" E.Alarme_email, E.Alarme_sms, E.Texte_email, E.Texte_sms"
" FROM TB_Historique H"
" JOIN TB_Events E ON E.Cle_primaire = H.ID_Source"
" WHERE H.Type_source = 6 AND H.Type IN (1, 2)" // TYPE_SOURCE_HISTORIQUE_EVENTS ; EVENT_DECLENCHEMENT, EVENT_FIN_DECLENCHEMENT
" AND (E.Alarme_email > 0 OR E.Alarme_sms > 0)"
" AND H.Date >= ?"
" ORDER BY H.Date"
" LIMIT 1000");
q.addBindValue(depuis);
if (!q.exec()) {
QJsonObject err;
err["status"] = "error";
err["message"] = q.lastError().text();
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::InternalServerError));
}
QJsonArray evenements;
while (q.next()) {
QJsonObject ev;
ev["date"] = q.value(0).toString();
ev["type"] = q.value(1).toInt();
ev["id_event"] = q.value(2).toInt();
ev["nom"] = q.value(3).toString();
ev["alarme_email"] = q.value(4).toInt();
ev["alarme_sms"] = q.value(5).toInt();
ev["texte_email"] = q.value(6).toString();
ev["texte_sms"] = q.value(7).toString();
evenements.append(ev);
}
QJsonObject reponse;
reponse["status"] = "ok";
reponse["evenements"] = evenements;
return withCors(QHttpServerResponse(QJsonDocument(reponse).toJson()));
});
// ------------------------------------------------------------------
// POST /archives/demande - demande à l'Appli de produire une archive
// IMMÉDIATEMENT (synthèse §50, étape 3d) : TB_Systeme.Demande_sauvegarde_bdd
// passe à 1 ; l'Appli le lit, remet son compteur de période à 0 (archive
// produite dans la seconde), puis remet l'indicateur à 0.
// Appelée par le VPS via NetBird (port 8080), quand un utilisateur ouvre la
// page "Données du bateau" sur le portail. Comme les autres routes
// /archives, elle n'est PAS accessible via le relais /api du nginx du CM5.
// ------------------------------------------------------------------
server.route("/archives/demande", QHttpServerRequest::Method::Post, [](const QHttpServerRequest &request) {
Q_UNUSED(request)
assurer_connexion_bdd();
// Existence de la ligne vérifiée à part : un UPDATE qui ne change rien
// (indicateur déjà à 1) renvoie aussi 0 ligne modifiée.
QSqlQuery existe;
existe.prepare("SELECT COUNT(*) FROM TB_Systeme WHERE Nom='Demande_sauvegarde_bdd'");
if (!existe.exec() || !existe.next() || existe.value(0).toInt() == 0) {
QJsonObject err;
err["status"] = "error";
err["message"] = "paramètre TB_Systeme.Demande_sauvegarde_bdd introuvable";
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::NotImplemented));
}
QSqlQuery q;
q.prepare("UPDATE TB_Systeme SET Valeur='1' WHERE Nom='Demande_sauvegarde_bdd'");
if (!q.exec()) {
QJsonObject err;
err["status"] = "error";
err["message"] = q.lastError().text();
return withCors(QHttpServerResponse(QJsonDocument(err).toJson(), QHttpServerResponder::StatusCode::InternalServerError));
}
QJsonObject reponse;
reponse["status"] = "ok";
return withCors(QHttpServerResponse(QJsonDocument(reponse).toJson()));
});
// ------------------------------------------------------------------
// GET /archives - liste les archives en attente de traitement par le VPS
// (cf synthèse §32.5). Remplace le transport sshpass/scp existant.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.