diff --git a/.current_version b/.current_version index e6d823b..e211a55 100644 --- a/.current_version +++ b/.current_version @@ -1 +1 @@ -261006_091623 \ No newline at end of file +261007_091503 \ No newline at end of file diff --git a/_version.h b/_version.h index 47c9fe1..91db8b1 100644 --- a/_version.h +++ b/_version.h @@ -1,6 +1,6 @@ #ifndef _VERSION_H #define _VERSION_H -#define VERSION "261006_091623" +#define VERSION "261007_091503" #endif // _VERSION_H diff --git a/main.cpp b/main.cpp index b6d1837..965de51 100644 --- a/main.cpp +++ b/main.cpp @@ -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. diff --git a/versions/shipheart_api_261006_171423 b/versions/shipheart_api_261006_171423 new file mode 100755 index 0000000..3721a42 Binary files /dev/null and b/versions/shipheart_api_261006_171423 differ diff --git a/versions/shipheart_api_261006_171445 b/versions/shipheart_api_261006_171445 new file mode 100755 index 0000000..bbd9688 Binary files /dev/null and b/versions/shipheart_api_261006_171445 differ diff --git a/versions/shipheart_api_261007_091452 b/versions/shipheart_api_261007_091452 new file mode 100755 index 0000000..2f5a59a Binary files /dev/null and b/versions/shipheart_api_261007_091452 differ diff --git a/versions/shipheart_api_261007_091503 b/versions/shipheart_api_261007_091503 new file mode 100755 index 0000000..c2c5dbd Binary files /dev/null and b/versions/shipheart_api_261007_091503 differ