Files
pws2mqtt-qt/barometertrend.h

253 lines
7.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <QObject>
#include <QVector>
#include <QDateTime>
#include <QtMath>
struct ForecastResult
{
QString message;
int urgency; // 0-5
QString colorCode; // "vert", "jaune", ...
bool snowRisk;
bool rainRisk;
bool stormRisk;
bool blackIce;
};
class BarometerTrend : public QObject
{
Q_OBJECT
public:
explicit BarometerTrend(QObject *parent = nullptr)
: QObject(parent)
{}
void addPressure(double pressure_hPa)
{
// Enregistrement de la nouvelle mesure
m_values.append(pressure_hPa);
m_timestamps.append(QDateTime::currentDateTime());
// Limiter la taille de lhistorique à 3 heures (360 mesures à 30s dintervalle)
const int maxSamples = 360;
while (m_values.size() > maxSamples)
{
m_values.removeFirst();
m_timestamps.removeFirst();
}
}
double currentPressure() const
{
return m_values.isEmpty() ? 0.0 : m_values.last();
}
// Moyenne glissante sur les dernières N mesures (par ex. 5 minutes)
double smoothedPressure(int samples = 10) const
{
if (m_values.isEmpty())
{
return 0.0;
}
int n = qMin(samples, m_values.size());
double sum = 0.0;
for (int i = m_values.size() - n; i < m_values.size(); ++i)
sum += m_values[i];
return sum / n;
}
// Variation de pression sur les dernières 3h
double deltaPressure3h() const
{
if (m_values.size() < 2)
{
return 0.0;
}
QDateTime now = QDateTime::currentDateTime();
QDateTime target = now.addSecs(-3 * 3600);
// Cherche la valeur la plus proche dil y a 3 heures
int idx = -1;
for (int i = 0; i < m_timestamps.size(); ++i)
{
if (m_timestamps[i] >= target)
{
idx = i;
break;
}
}
if (idx == -1)
{
idx = 0; // Pas assez vieux, on prend la plus ancienne
}
double p_now = smoothedPressure();
double p_past = m_values[idx];
return p_now - p_past;
}
ForecastResult forecast(double temperatureC, double humidityPercent) const
{
ForecastResult r;
double p = currentPressure();
double d = deltaPressure3h();
r.snowRisk = false;
r.rainRisk = false;
r.stormRisk = false;
r.blackIce = false;
// Logique combinée pression / tendance
if (p >= 1020 && d >= +3)
{
r.message = "Très beau temps durable";
r.urgency = 0;
r.colorCode = "sunny";
}else if (p >= 1020 && d >= +1)
{
r.message = "Beau temps durable";
r.urgency = 0;
r.colorCode = "sunny";
}else if (p >= 1020 && d < -3)
{
r.message = "Beau, mais rapide dégradation";
r.urgency = 4;
r.colorCode = "sun_behind_large_cloud";
}else if (p >= 1020 && d < -1)
{
r.message = "Beau, mais possible dégradation";
r.urgency = 1;
r.colorCode = "sun_behind_small_cloud";
}else if (p >= 1020 && d < 0.5)
{
r.message = "Beau temps stable";
r.urgency = 0;
r.colorCode = "sunny";
}else if (p >= 1010 && d >= +3)
{
r.message = "Rapide amélioration du temps";
r.urgency = 4;
r.colorCode = "sun_behind_small_cloud";
}else if (p >= 1010 && d >= +1)
{
r.message = "Amélioration du temps";
r.urgency = 0;
r.colorCode = "sun_behind_large_cloud";
}else if (p >= 1010 && d <= -3)
{
r.message = "Fort risque de pluie ou vent";
r.urgency = 4;
r.colorCode = "sun_behind_rain_cloud";
}else if (p >= 1010 && d <= -1)
{
r.message = "Risque de pluie ou vent";
r.urgency = 2;
r.colorCode = "sun_behind_rain_cloud";
}else if (p >= 1010 && d <= 0.5)
{
r.message = "Nuageux avec des éclaircies";
r.urgency = 2;
r.colorCode = "sun_behind_large_cloud";
}else if (p >= 1000 && d >= +3)
{
r.message = "Variable, amélioration rapide";
r.urgency = 4;
r.colorCode = "sun_behind_large_cloud";
}else if (p >= 1000 && d >= +1)
{
r.message = "Variable, tendance au beau";
r.urgency = 0;
r.colorCode = "sun_behind_large_cloud";
}else if (p >= 1000 && d <= -3)
{
r.message = "Pluie ou perturbation, dégradation rapide";
r.urgency = 4;
r.colorCode = "cloud_with_rain";
}else if (p >= 1000 && d <= -1)
{
r.message = "Pluie ou perturbation";
r.urgency = 2;
r.colorCode = "cloud_with_rain";
}else if (p < 990 && d <= -3)
{
r.message = "Tempête ou orage";
r.urgency = 5;
r.colorCode = "cloud_with_lightning";
}else if (p < 1000 && d >= +3)
{
r.message = "Accalmie temporaire, amélioration rapide";
r.urgency = 1;
r.colorCode = "sun_behind_rain_cloud";
}else if (p < 1000 && d >= +1)
{
r.message = "Accalmie temporaire";
r.urgency = 1;
r.colorCode = "sun_behind_rain_cloud";
}else if (p < 1000 && d <= -1)
{
r.message = "Mauvais temps durable";
r.urgency = 4;
r.colorCode = "cloud_with_rain";
}
if (qAbs(d) < 0.5)
{
r.message = "Stable, pas de changement significatif";
r.urgency = 0;
}
// Risque de neige
if (p < 1000 && d < -1 && temperatureC <= 1.0 && humidityPercent > 80.0)
{
r.snowRisk = true;
r.message += " — Risque de neige";
r.urgency = qMax(r.urgency, 3);
r.colorCode += "snowflake,";
}
// Risque de pluie
else if (p < 1010 && d < -1 && temperatureC > 1.0 && humidityPercent > 70.0)
{
r.rainRisk = true;
r.message += " — Risque de pluie";
r.urgency = qMax(r.urgency, 2);
r.colorCode += "cloud_with_rain,";
}
// Risque dorage
if (p < 995 && d < -3 && temperatureC > 20.0 && humidityPercent > 70.0)
{
r.stormRisk = true;
r.message += " ⚡ Risque dorage";
r.urgency = qMax(r.urgency, 4);
r.colorCode += "cloud_with_lightning,";
}
if (temperatureC <= 0.5 && humidityPercent >= 85.0) {
// conditions classiques de gel
if (d >= -1 && d <= +1)
{
r.blackIce = true; // temps stable = ciel clair = refroidissement
}else if (d < -1 && p > 995)
{
r.blackIce = true; // arrivée d'air humide froid
}
}
if (r.blackIce)
{
r.message += "Risque de verglas";
r.colorCode += "ice_cube,";
r.urgency = qMax(r.urgency, 4);
}
return r;
}
private:
QVector<double> m_values;
QVector<QDateTime> m_timestamps;
};