790 lines
26 KiB
C++
790 lines
26 KiB
C++
#include "pws2mqtt.h"
|
||
#include "barometertrend.h"
|
||
#include "mqtt.h"
|
||
//#include "httpserver.h"
|
||
#include <cstring>
|
||
#include <unistd.h>
|
||
#include <QtGlobal>
|
||
#include <iostream>
|
||
#include <QList>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <QtHttpServer/QHttpServer>
|
||
#include <QtHttpServer/QHttpServerRequest>
|
||
#include <curl/curl.h>
|
||
#include <QtMath>
|
||
#include <QImage>
|
||
#include <QTransform>
|
||
#include <stdio.h>
|
||
#include <sys/stat.h>
|
||
#include "utcicalculator.h"
|
||
|
||
extern MqttClient *mqttClient;
|
||
extern Pws2mqtt *pws2mqtt;
|
||
extern QHttpServer *httpServer;
|
||
extern BarometerTrend *baro;
|
||
UtciCalculator calc;
|
||
|
||
using namespace std;
|
||
|
||
QStringList previsionList
|
||
{
|
||
"Temps variable (incertain).", \
|
||
"Beau temps stable (anticyclone).", \
|
||
"Beau temps en baisse (anticyclone).", \
|
||
"Amélioration progressive (éclaircies).", \
|
||
"Risque de pluie légère ou nuages.", \
|
||
"Dégradation marquée (pluie/vent/orage).", \
|
||
"Tempête ou dépression forte (vigilance).", \
|
||
"Temps stable"
|
||
};
|
||
|
||
// Callback for curl library
|
||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||
{
|
||
(void)contents; // Évite les warnings de compilation
|
||
(void)userp;
|
||
return size * nmemb; // On ne traite pas les données reçues
|
||
}
|
||
|
||
|
||
QMap <QByteArray, QString> propertyList;
|
||
QMap <QByteArray, QString> precPropertyList;
|
||
QMap <QByteArray, double> propertiesValue;
|
||
QMap <QByteArray, QPair<QString, QByteArray>> propertyName
|
||
{
|
||
{"tempf", {"Température extérieure", "°C"}},
|
||
{"humidity", {"Humidité extérieure", "%"}},
|
||
{"dewptf", {"Point de rosée", "°C"}},
|
||
{"windchill", {"Température ressentie", "°C"}},
|
||
{"winddir", {"Direction du vent", "°"}},
|
||
{"windspeedmph", {"Vitesse du vent", " km/h"}},
|
||
{"windgustmph", {"Rafales", " km/h"}},
|
||
{"rainin", {"Pluie", " mm/h"}},
|
||
{"dailyrainin", {"Pluie de la journée", " mm"}},
|
||
{"monthlyrainin", {"Pluie du mois", " mm"}},
|
||
{"yearlyrainin", {"Pluie de l'année", " mm"}},
|
||
{"solarradiation", {"Énergie solaire", " W/m²"}},
|
||
{"indoortempf", {"Température intérieure", "°C"}},
|
||
{"indoorhumidity", {"Humidité intérieure", "%"}},
|
||
{"baromin", {"Pression atmosphérique", " hPa"}},
|
||
{"lowbatt", {"Alerte batterie faible", ""}},
|
||
{"UV", {"Alerte UV", ""}}
|
||
};
|
||
|
||
QList <QList <QVariant>> forceVent
|
||
{
|
||
// { max wind speed, name, priority}
|
||
{1, "Temps calme", 1},
|
||
{5, "Très légère brise", 1},
|
||
{11, "Légère brise", 1},
|
||
{19, "Petite brise", 1},
|
||
{28, "Jolie brise", 1},
|
||
{38, "Bonne brise", 1},
|
||
{49, "Vent frais", 3},
|
||
{61, "Grand vent", 4},
|
||
{74, "Vent fort", 4},
|
||
{88, "Vent violent", 5},
|
||
{117, "Tempête", 5},
|
||
{1000, "Ouragan", 5}
|
||
};
|
||
|
||
Pws2mqtt::Pws2mqtt()
|
||
{
|
||
this->init();
|
||
}
|
||
|
||
Pws2mqtt::~Pws2mqtt()
|
||
{
|
||
}
|
||
|
||
void Pws2mqtt::init()
|
||
{
|
||
debug(DEBUGMACRO, "init http server", DEBUG);
|
||
httpServer->setMissingHandler([](const QHttpServerRequest &request, QHttpServerResponder &&responder)
|
||
{
|
||
(void) responder;
|
||
debug(DEBUGMACRO, "body " + request.url().toString(), WARNING);
|
||
return QHttpServerResponse("404 - Page non trouvée. Route par défaut.", QHttpServerResponse::StatusCode::NotFound);
|
||
//responder.write(QHttpServerResponse("404 - Page non trouvée. Route par défaut.", QHttpServerResponse::StatusCode::NotFound));
|
||
});
|
||
|
||
httpServer->route("/", [](const QHttpServerRequest &request)
|
||
{
|
||
QList<std::pair<QByteArray, QByteArray>> headersList = request.headers().toList();
|
||
debug(DEBUGMACRO, "Remote address" + request.remoteAddress().toString(), WARNING);
|
||
return QHttpServerResponse("text/plain", "Failed\n");
|
||
});
|
||
httpServer->route("/query", [this](const QHttpServerRequest &request)
|
||
{
|
||
QByteArray data;
|
||
QList<std::pair<QString, QString>> queryList = request.query().queryItems();
|
||
|
||
//QTextStream result(&data);
|
||
|
||
if (queryList.isEmpty())
|
||
{
|
||
debug(DEBUGMACRO, "Request query is empty", WARNING);
|
||
}else
|
||
{
|
||
debug(DEBUGMACRO, "Request query :" + request.query().toString() , DEBUG);
|
||
this->parseData(queryList);
|
||
debug(DEBUGMACRO, "Returning 'success'", DEBUG);
|
||
}
|
||
//mqttClient.send_message(jsonString);
|
||
|
||
return QHttpServerResponse("text/plain", "Success\n");
|
||
});
|
||
}
|
||
|
||
void Pws2mqtt::listeningHttp()
|
||
{
|
||
//QByteArray data;
|
||
debug (DEBUGMACRO, "listening http requests", DEBUG);
|
||
const auto port = httpServer->listen(QHostAddress::Any, 5000);
|
||
if (!port)
|
||
{
|
||
debug(DEBUGMACRO, "Http Server failed to listen on a port.", ERROR);
|
||
}
|
||
debug(DEBUGMACRO, "Listening on port " + QString::number(port));
|
||
}
|
||
|
||
void Pws2mqtt::parseData(QList<std::pair<QString, QString>> queryList)
|
||
{
|
||
debug(DEBUGMACRO, "Parsing Datas", DEBUG);
|
||
|
||
QString jsonString = "{";
|
||
QString deviceString = "\"device\": {\"ieeeAddress\": \"" + mqttClient->macAddress + "\", \"type\": \"" + mqttClient->type + "\", \"powerSource\": \"Battery\"";
|
||
QString notif = "";
|
||
QStringList priorityList {"", "min", "low", "default", "High", "urgent"};
|
||
QString attachment = "";
|
||
QString tag = "";
|
||
quint8 priority = 2;
|
||
double propertyValue = 0;
|
||
bool propertyFlag = false;
|
||
bool deviceFlag = false;
|
||
static QDateTime timer = QDateTime::currentDateTime().addSecs(-2000);
|
||
|
||
debug(DEBUGMACRO, "looping list of query", DEBUG);
|
||
|
||
for (QPair<QString, QString> pair : queryList)
|
||
{
|
||
debug(DEBUGMACRO, pair.first + " = " + pair.second, DEBUG);
|
||
QByteArray name = pair.first.toLatin1();
|
||
QByteArray value = pair.second.toLatin1();
|
||
float fValue = value.toDouble();
|
||
|
||
if (this->deviceProperties.contains(name))
|
||
{
|
||
if(deviceFlag == false)
|
||
{
|
||
deviceFlag = true;
|
||
}else
|
||
{
|
||
deviceString.append(", ");
|
||
}
|
||
deviceString += "\"" + name + "\": ";
|
||
deviceString += pair.second;
|
||
}else
|
||
{
|
||
if(propertyFlag == false)
|
||
{
|
||
propertyFlag = true;
|
||
}else
|
||
{
|
||
jsonString.append(", ");
|
||
}
|
||
jsonString.append("\"" + name + "\": ");
|
||
jsonString.append(pair.second);
|
||
|
||
if (name == "tempf")
|
||
{
|
||
static QDateTime timeTemp = QDateTime::currentDateTime().addSecs(-600);
|
||
propertyValue = round(fahrenheitToCelsius(fValue));
|
||
debug (DEBUGMACRO, "timeTemp = " + timeTemp.time().toString() + " - current :" + QDateTime::currentDateTime().toString() , DEBUG);
|
||
|
||
if (compare (propertiesValue[name], propertyValue, 1) and timeTemp < QDateTime::currentDateTime())
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second, QByteArray::number(qPow(propertyValue, 1.0)));
|
||
//debug (DEBUGMACRO, "", DEBUG);
|
||
timeTemp = timeTemp.currentDateTime().addSecs(300);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, propertyName[name].second, QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
}
|
||
}else if (name == "humidity")
|
||
{
|
||
propertyValue = value.toFloat();
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
|
||
if (compare (propertiesValue[name], propertyValue, 3))
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , value);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, propertyName[name].second, QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
}
|
||
}else if (name == "winddir")
|
||
{
|
||
propertyValue = value.toFloat();
|
||
rotateAndSaveImage(this->inputPath, this->outputPath, (qreal)propertyValue);
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, propertyName[name].second, QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
}else if (name == "windspeedmph")
|
||
{
|
||
QString msg = "";
|
||
quint8 i;
|
||
static QDateTime timeWind = QDateTime::currentDateTime().addSecs(-600);
|
||
quint8 windPriority = 1;
|
||
|
||
propertiesValue["vent"] = round(mphTokmh(value.toFloat()));
|
||
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertiesValue["vent"]), DEBUG);
|
||
|
||
for (i=0; i<forceVent.size();i++)
|
||
{
|
||
if (propertiesValue["vent"] <= forceVent[i][0].toDouble())
|
||
{
|
||
msg = forceVent[i][1].toString();
|
||
windPriority = forceVent[i][2].toUInt();
|
||
break;
|
||
}
|
||
}
|
||
|
||
propertyList[name] = formatNotifString ("Vent - " + msg, propertyName[name].second , QByteArray::number(propertiesValue["vent"]));
|
||
propertiesValue["forcevent"] = i;
|
||
if (i >= 5)
|
||
{
|
||
attachment = this->outputPath;
|
||
}
|
||
|
||
if (propertiesValue["forcevent"] != i or propertiesValue["rafales"] != i)
|
||
{
|
||
priority = qMax(priority, windPriority);
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
}else if (name == "windgustmph")
|
||
{
|
||
QString msg = "";
|
||
static QDateTime timeWind = QDateTime::currentDateTime().addSecs(-600);
|
||
|
||
propertiesValue[name] = round(mphTokmh(value.toFloat()));
|
||
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertiesValue["rafale"]), DEBUG);
|
||
|
||
propertyList[name] = formatNotifString (propertyName[name].first, propertyName[name].second , QByteArray::number(propertiesValue[name]));
|
||
|
||
if (propertiesValue["rafales"] > 50)
|
||
{
|
||
priority = qMax(priority, (quint8)4);
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
}else if (name == "rainin")
|
||
{
|
||
static double ecart;
|
||
quint8 raininPriority = 1;
|
||
propertyValue = round(pair.second.toFloat()*100)/100;
|
||
if (propertyValue == 0)
|
||
{
|
||
ecart = 0.0001;
|
||
}else
|
||
{
|
||
ecart = 0.01;
|
||
}
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, ecart))
|
||
{
|
||
QString pluviosite = getPluviosite(propertyValue, raininPriority);
|
||
priority = setPriority (priority, raininPriority);
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
propertyList[name] = formatNotifString(pluviosite + " : ", propertyName[name].second, QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
}else if (name == "dailyrainin")
|
||
{
|
||
static double ecart;
|
||
propertyValue = round(pair.second.toFloat()*100)/100;
|
||
if (propertyValue == 0)
|
||
{
|
||
ecart = 0.0001;
|
||
}else
|
||
{
|
||
ecart = 0.01;
|
||
}
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, ecart))
|
||
{
|
||
//priority = setPriority (priority, 3);
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, propertyName[name].second, QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
}else if (name == "baromin")
|
||
{
|
||
//static QDateTime timePrevision = QDateTime::currentDateTime().addSecs(-1000);
|
||
|
||
propertyValue = round(tohPa(pair.second.toFloat()) * 100) / 100;
|
||
debug (DEBUGMACRO, "Barometre en hPa : " + QByteArray::number(propertyValue), DEBUG);
|
||
baro->addPressure(propertyValue);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, "", QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
|
||
static QString prevision;
|
||
auto ret = baro->forecast(propertiesValue["tempf"], propertiesValue["humidity"]);
|
||
|
||
QString newPrevision = ret.message;
|
||
if (prevision != newPrevision)
|
||
{
|
||
prevision = newPrevision;
|
||
propertyList["prevision"] = prevision;
|
||
priority = setPriority(priority, ret.urgency);
|
||
tag += ret.icons;
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
}else if (name == "UV")
|
||
{
|
||
static QDateTime timeUV = QDateTime::currentDateTime().addSecs(-600);
|
||
propertyValue = pair.second.toUInt();
|
||
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, 1) and timeUV < QDateTime::currentDateTime())
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , value);
|
||
if (propertyValue == 5 )
|
||
priority = setPriority (priority, 4);
|
||
if (propertyValue >= 6 )
|
||
priority = setPriority (priority, 5);
|
||
timeUV = timeUV.currentDateTime().addSecs(300);
|
||
propertyList[name] = formatNotifString(propertyName[name].first, "", QByteArray::number(propertyValue));
|
||
propertiesValue[name] = propertyValue;
|
||
debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
}
|
||
debug (DEBUGMACRO, "priority = " + QString::number(priority), DEBUG);
|
||
|
||
}else if (name == "solarradiation")
|
||
{
|
||
propertiesValue[name] = round(pair.second.toFloat()*100/100);
|
||
}
|
||
}
|
||
}
|
||
propertiesValue["windchill"] = calc.computeUTCI(propertiesValue["tempf"], propertiesValue["vent"], propertiesValue["solarradiation"], propertiesValue["humidity"]);
|
||
propertyList["windchill"] = formatNotifString(propertyName["windchill"].first, propertyName["windchill"].second, QByteArray::number(propertiesValue["windchill"]));
|
||
//windChill(propertiesValue["tempf"], propertiesValue["vent"]);
|
||
//calculerHumidex(propertiesValue["tempf"], propertiesValue["humidity"]);
|
||
|
||
if (!jsonString.isEmpty())
|
||
{
|
||
debug(DEBUGMACRO, "json string : " + jsonString, DEBUG);
|
||
jsonString = jsonString +", " + deviceString + "}}";
|
||
mqttClient->send_message(jsonString);
|
||
}else
|
||
{
|
||
debug(DEBUGMACRO, "No values to send", DEBUG);
|
||
}
|
||
|
||
debug(DEBUGMACRO, "current datetime : " + QDateTime::currentDateTime().toString() + ", timer = " + timer.toString(), DEBUG);
|
||
|
||
if (priority > 3 or QDateTime::currentDateTime() > timer.addSecs(1800))
|
||
{
|
||
bool changed = false;
|
||
timer = QDateTime::currentDateTime();
|
||
debug(DEBUGMACRO, "looping to fill notif, priority = " + QString::number(priority), DEBUG);
|
||
|
||
if (precPropertyList.size() == 0)
|
||
{
|
||
changed = true;
|
||
}
|
||
for (auto [name, value]: propertyList.asKeyValueRange())
|
||
{
|
||
if (precPropertyList.contains(name))
|
||
{
|
||
if (precPropertyList[name] != propertyList[name])
|
||
{
|
||
debug(DEBUGMACRO, "changed = true", DEBUG);
|
||
changed = true;
|
||
}
|
||
}
|
||
|
||
debug(DEBUGMACRO, "Name = " + name + ", value = " + value, DEBUG);
|
||
if (! (name == "prevision"))
|
||
{
|
||
notif += propertyList[name];
|
||
}
|
||
}
|
||
notif += "**Prévisions à 12/24h** \n" + propertyList["prevision"];
|
||
debug(DEBUGMACRO, "calling notify with notif = #" + notif + "#", DEBUG);
|
||
if (changed)
|
||
{
|
||
notify (notif, priorityList[priority], attachment, tag);
|
||
precPropertyList = propertyList;
|
||
}
|
||
}
|
||
debug(DEBUGMACRO, "parseData: Returning", DEBUG);
|
||
}
|
||
|
||
double calculerUTCI(double temperature, double humiditeRelative, double vitesseVent, double rayonnement)
|
||
{
|
||
double e = (humiditeRelative / 100.0) * 6.105 * exp((17.27 * temperature) / (237.7 + temperature));
|
||
debug(DEBUGMACRO, "UTCI => e = " + QString::number(e), DEBUG);
|
||
double V = vitesseVent * 5.0 / 18.0; // Vitesse du vent en m/s
|
||
debug(DEBUGMACRO, "UTCI => V = " + QString::number(V), DEBUG);
|
||
|
||
double utci = temperature +
|
||
(0.607562 + 0.022437 * e + 7.3869e-4 * temperature * e - 3.5582e-6 * temperature * temperature * e) +
|
||
(-11.4 + 0.11 * temperature + 0.55 * V) +
|
||
(0.0023 * temperature * temperature - 0.118 * V - 0.0014 * temperature * V);
|
||
debug(DEBUGMACRO, "UTCI = " + QString::number(utci), DEBUG);
|
||
|
||
// Ajustement simplifié pour le rayonnement
|
||
double ref = 200.0; // Rayonnement de référence (W/m²)
|
||
double k = 0.02; // Coefficient empirique
|
||
utci = utci + k * (rayonnement - ref);
|
||
debug(DEBUGMACRO, "UTCI = " + QString::number(utci), DEBUG);
|
||
return round(utci * 100) / 100;
|
||
}
|
||
|
||
/*double windChill(double airT, double vent)
|
||
{
|
||
double w = 0;
|
||
|
||
if (airT > 10 or vent < 4.8)
|
||
{
|
||
return airT;
|
||
} else
|
||
{
|
||
w = 13.12 + 0.6215 * airT - 11.37 * pow(vent, 0.16) + 0.3965 * airT * pow(vent, 0.16);
|
||
debug(DEBUGMACRO, "windChill = " + QString::number(w), DEBUG);
|
||
return w;
|
||
}
|
||
}*/
|
||
|
||
/*double calculerHumidex(double temperature, double humiditeRelative)
|
||
{
|
||
// Calcul de la température du point de rosée (T_rosée)
|
||
double T_rosee = (243.04 * (log(humiditeRelative / 100.0) + (17.625 * temperature) / (243.04 + temperature))) / (17.625 - (log(humiditeRelative / 100.0) + (17.625 * temperature) / (243.04 + temperature)));
|
||
|
||
// Calcul de l'Humidex (H)
|
||
double H = temperature + 0.5555 * (6.11 * exp(5417.7530 * (1.0 / 273.16 - 1.0 / (273.15 + T_rosee))) - 10.0);
|
||
debug(DEBUGMACRO, "humidex = " + QString::number(H), DEBUG);
|
||
|
||
return H;
|
||
}*/
|
||
|
||
QString getPluviosite(double value, quint8 &priority)
|
||
{
|
||
if (value < 1)
|
||
{
|
||
return "Pluie fine, bruine";
|
||
}else if (value < 5)
|
||
{
|
||
return "Pluie Modérée";
|
||
}else if (value < 10)
|
||
{
|
||
priority = 4;
|
||
return "Pluie forte";
|
||
}else if (value < 30)
|
||
{
|
||
priority = 5;
|
||
return "Pluie Très forte, risque d'inondation";
|
||
}else
|
||
{
|
||
priority = 5;
|
||
return "Pluie diluvienne, risque élevé d'inondations, crues";
|
||
}
|
||
}
|
||
|
||
QString previsionMeteo(double currentPressure, double variation3h, quint8 &priority)
|
||
{
|
||
QString variation = "";
|
||
|
||
priority = 3;
|
||
debug (DEBUGMACRO, "begin", DEBUG);
|
||
|
||
if (variation3h == 0.0)
|
||
{
|
||
variation = " - temps stable";
|
||
}else if (variation3h > 0.2)
|
||
{
|
||
variation = " en amélioration rapide";
|
||
}else if (variation3h < -2.0)
|
||
{
|
||
variation = "en dégradation rapide";
|
||
}else if (variation3h > 0)
|
||
{
|
||
variation = " en amélioration";
|
||
}else if (variation3h <0)
|
||
{
|
||
variation = " en dégradation";
|
||
}
|
||
|
||
if (currentPressure > 1020.0)
|
||
{
|
||
return "Beau temps (anticyclone)" + variation;
|
||
} else if (currentPressure > 1010.0 && currentPressure <= 1020.0)
|
||
{
|
||
return "Éclaircies" + variation;
|
||
} else if (currentPressure > 1000.0 && currentPressure < 1009.0)
|
||
{
|
||
priority = 3;
|
||
return "Temps variable, risque de pluie légère" + variation;
|
||
} else if (currentPressure >=990 && currentPressure <= 1000.0)
|
||
{
|
||
priority = 5;
|
||
return "Pluie/vent/orage" + variation;
|
||
} else if (currentPressure < 990.0)
|
||
{
|
||
priority = 5;
|
||
return "Tempête ou dépression forte (vigilance)" + variation;
|
||
}
|
||
return variation;
|
||
}
|
||
|
||
/*QString pressureVariation(double currentPressure, quint8 &priority)
|
||
{
|
||
const int NB_MESURES_3H = 360; // 3h × 120 mesures/heure (1 mesure toutes les 30s)
|
||
static QVector<double> historiquePressions;
|
||
debug(DEBUGMACRO, "PressureVariation : current pressure = " + QByteArray::number(currentPressure), DEBUG);
|
||
|
||
historiquePressions.append(currentPressure);
|
||
|
||
// Si on a assez de mesures pour couvrir 3h
|
||
if (historiquePressions.size() > NB_MESURES_3H)
|
||
{
|
||
debug(DEBUGMACRO, "historiquePressions > " + QByteArray::number(NB_MESURES_3H), DEBUG);
|
||
historiquePressions.erase(historiquePressions.begin());
|
||
}
|
||
debug(DEBUGMACRO, "taille de historiquePression : " + QByteArray::number(historiquePressions.size()), DEBUG);
|
||
// Calcul de la variation sur 3h si on a assez de mesures
|
||
if (historiquePressions.size() == NB_MESURES_3H)
|
||
{
|
||
double pressionInitiale = historiquePressions.front();
|
||
double pressionFinale = historiquePressions.back();
|
||
double variation = pressionFinale - pressionInitiale;
|
||
|
||
debug(DEBUGMACRO, "Pression actuelle : " + QString::number(pressionFinale) + " hPa", DEBUG);
|
||
debug(DEBUGMACRO, "Variation sur 3h : " + QString::number(variation) + " hPa", DEBUG);
|
||
|
||
// Prévision météo
|
||
QString prevision = previsionMeteo(pressionFinale, variation, priority);
|
||
debug(DEBUGMACRO, "Prévision : " + prevision, DEBUG);
|
||
|
||
// Exemple : Envoi d'une alerte si nécessaire
|
||
|
||
debug(DEBUGMACRO, "ending pressureVariation with result", DEBUG);
|
||
return prevision;
|
||
}else
|
||
{
|
||
static QTime time = QTime::currentTime().addSecs(NB_MESURES_3H * 30);
|
||
return "Première prévision à " + time.toString();
|
||
}
|
||
debug(DEBUGMACRO, "ending pressureVariation no result", DEBUG);
|
||
return "";
|
||
}*/
|
||
|
||
quint8 setPriority (quint8 currentPriority, quint8 newPriority)
|
||
{
|
||
if (newPriority > currentPriority)
|
||
{
|
||
return newPriority;
|
||
}else
|
||
{
|
||
return currentPriority;
|
||
}
|
||
}
|
||
|
||
double fahrenheitToCelsius (double fahrenheit)
|
||
{
|
||
return (fahrenheit - 32.0) * 5.0 / 9.0;
|
||
}
|
||
|
||
double tohPa (double value)
|
||
{
|
||
return round(value * 33.8639 * 100) / 100;
|
||
}
|
||
|
||
double mphTokmh (double value)
|
||
{
|
||
return value * 1.60934;
|
||
}
|
||
|
||
bool compare (double value, double currentValue, double ecart)
|
||
{
|
||
|
||
debug(DEBUGMACRO, "value: " + QByteArray::number(value) + "testValue: " + QByteArray::number(currentValue), DEBUG);
|
||
|
||
if (currentValue <= (value - ecart) or currentValue >= (value + ecart))
|
||
{
|
||
debug(DEBUGMACRO, "compare return true", DEBUG);
|
||
return true;
|
||
}else
|
||
{
|
||
debug(DEBUGMACRO, "compare return false", DEBUG);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
QString formatNotifString (QString name, QString unit ,QByteArray value)
|
||
{
|
||
QString text = "- " + name + " : " + value;
|
||
if (!unit.isEmpty())
|
||
{
|
||
text += unit;
|
||
//"- " + propertyName[name].first + " : " + value + " " + propertyName[name].second + " \n";
|
||
}
|
||
return text += " \n";
|
||
}
|
||
|
||
static size_t ReadFile(void *ptr, size_t size, size_t nmemb, void *stream) {
|
||
FILE *f = (FILE *)stream;
|
||
size_t n = fread(ptr, size, nmemb, f);
|
||
return n;
|
||
}
|
||
|
||
void notify(QString notif, QString priority, QString inputPath, QString tag)
|
||
{
|
||
CURL *curl;
|
||
CURLcode res;
|
||
std::string readBuffer;
|
||
|
||
priority = "Priority: " + priority;
|
||
debug (DEBUGMACRO, "notifying at priority " + priority + "with tag : " + tag + " - message : " + notif, DEBUG);
|
||
|
||
// Initialise libcurl
|
||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||
curl = curl_easy_init();
|
||
if (curl)
|
||
{
|
||
// Définis les en-têtes pour le titre et les priorités
|
||
struct curl_slist *headers = NULL;
|
||
headers = curl_slist_append(headers, ("Tags: " + tag).toStdString().c_str());
|
||
headers = curl_slist_append(headers, "Title: Météo");
|
||
headers = curl_slist_append(headers, priority.toStdString().c_str());
|
||
headers = curl_slist_append(headers, "Markdown: yes");
|
||
headers = curl_slist_append(headers, "Config: /etc/ntfy.client.yml");
|
||
headers = curl_slist_append(headers, "Firebase: no");
|
||
|
||
/*curl_mime *mime;
|
||
curl_mimepart *part;
|
||
|
||
// Initialise la structure mime
|
||
mime = curl_mime_init(curl);
|
||
|
||
// Ajoute le champ "message" (ton texte de notification)
|
||
part = curl_mime_addpart(mime);
|
||
curl_mime_name(part, "message");
|
||
curl_mime_data(part, notif.toUtf8().constData(), CURL_ZERO_TERMINATED);
|
||
*/
|
||
// Configure la requête POST
|
||
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:81/Meteo");
|
||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notif.toUtf8().constData());
|
||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||
|
||
// Exécute la requête
|
||
|
||
res = curl_easy_perform(curl);
|
||
|
||
// Vérifie les erreurs
|
||
if (res != CURLE_OK)
|
||
{
|
||
debug(DEBUGMACRO, "Erreur libcurl :" + QString(curl_easy_strerror(res)), DEBUG);
|
||
} else
|
||
{
|
||
debug(DEBUGMACRO, "Notification envoyée avec succès", DEBUG);
|
||
}
|
||
|
||
// Nettoie les ressources
|
||
//curl_mime_free(mime);
|
||
curl_slist_free_all(headers);
|
||
curl_easy_cleanup(curl);
|
||
}
|
||
// Nettoie libcurl
|
||
curl_global_cleanup();
|
||
|
||
if (!inputPath.isEmpty())
|
||
{
|
||
FILE *fd = fopen(inputPath.toStdString().c_str(), "rb");
|
||
|
||
if (!fd) {
|
||
perror("Erreur lors de l'ouverture du fichier");
|
||
return;
|
||
}
|
||
// Initialise libcurl
|
||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||
curl = curl_easy_init();
|
||
if (curl)
|
||
{
|
||
// Définis les en-têtes pour le titre et les priorités
|
||
struct curl_slist *headers = NULL;
|
||
headers = curl_slist_append(headers, "Title: Météo");
|
||
headers = curl_slist_append(headers, priority.toStdString().c_str());
|
||
headers = curl_slist_append(headers, "Config: /etc/ntfy.client.yml");
|
||
headers = curl_slist_append(headers, "Firebase: no");
|
||
headers = curl_slist_append(headers, "Content-Type: image/png");
|
||
headers = curl_slist_append(headers, "X-Original-Size: true");
|
||
headers = curl_slist_append(headers, "X-Filename: fleche.png");
|
||
|
||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Configurer l'URL
|
||
curl_easy_setopt(curl, CURLOPT_URL, "localhost:81/Meteo");
|
||
|
||
// Utiliser la méthode PUT (comme `curl -T`)
|
||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||
|
||
// Lire le fichier et l'envoyer en tant que body
|
||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadFile);
|
||
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
|
||
|
||
// Définir la taille du fichier (optionnel mais recommandé)
|
||
struct stat file_info;
|
||
fstat(fileno(fd), &file_info);
|
||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
|
||
|
||
// Exécuter la requête
|
||
res = curl_easy_perform(curl);
|
||
// Vérifie les erreurs
|
||
if (res != CURLE_OK)
|
||
{
|
||
debug(DEBUGMACRO, "Erreur libcurl :" + QString(curl_easy_strerror(res)), DEBUG);
|
||
} else
|
||
{
|
||
debug(DEBUGMACRO, "Notification envoyée avec succès", DEBUG);
|
||
}
|
||
// Nettoyer
|
||
fclose(fd);
|
||
curl_easy_cleanup(curl);
|
||
}
|
||
// Nettoie libcurl
|
||
curl_global_cleanup();
|
||
}
|
||
}
|
||
|
||
void rotateAndSaveImage(const QString &inputPath, const QString &outputPath, qreal angle)
|
||
{
|
||
QImage image(inputPath);
|
||
if (image.isNull())
|
||
{
|
||
debug (DEBUGMACRO, "Impossible de charger l'image : " + inputPath, WARNING);
|
||
return;
|
||
}
|
||
|
||
// Crée une transformation pour pivoter l'image
|
||
QTransform transform;
|
||
// Décale le centre de l'image à l'origine
|
||
transform.translate(-image.width() / 2.0, -image.height() / 2.0);
|
||
// Applique la rotation
|
||
transform.rotate(angle);
|
||
// Remet le centre à sa position d'origine
|
||
transform.translate(image.width() / 2.0, image.height() / 2.0);
|
||
|
||
// Applique la transformation
|
||
QImage rotatedImage = image.transformed(transform, Qt::SmoothTransformation);
|
||
|
||
// Enregistre l'image pivotée
|
||
if (!rotatedImage.save(outputPath))
|
||
{
|
||
debug (DEBUGMACRO, "Impossible d'enregistrer l'image : ", WARNING);
|
||
}
|
||
}
|