776 lines
24 KiB
C++
776 lines
24 KiB
C++
#include "pws2mqtt.h"
|
||
#include "mqtt.h"
|
||
//#include "httpserver.h"
|
||
#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>
|
||
|
||
extern MqttClient *mqttClient;
|
||
extern Pws2mqtt *pws2mqtt;
|
||
extern QHttpServer *httpServer;
|
||
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, QVariant> propertyList;
|
||
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"}},
|
||
{"windchillf", {"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", 5},
|
||
{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 = "{";
|
||
bool propertyFlag = false;
|
||
bool deviceFlag = false;
|
||
// QString topic;
|
||
QString deviceString = "\"device\": {\"ieeeAddress\": \"" + mqttClient->macAddress + "\", \"type\": \"" + mqttClient->type + "\", \"powerSource\": \"Battery\"";
|
||
QString notif = "";
|
||
double propertyValue = 0;
|
||
QStringList priorityList {"", "min", "low", "default", "High", "urgent"};
|
||
quint8 priority = 2;
|
||
static qreal winddir = 0;
|
||
QString attachment = "";
|
||
bool changed = false;
|
||
|
||
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] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
/*}else if (name == "indoortempf")
|
||
{
|
||
static QDateTime timeIndoorTemp = QDateTime::currentDateTime().addSecs(-600);
|
||
propertyValue = round(fahrenheitToCelsius(pair.second.toFloat()));
|
||
if (compare (propertyList[name], propertyValue, 1) and timeIndoorTemp < QDateTime::currentDateTime())
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , QByteArray::number(qPow(propertyValue, 1.0)));
|
||
debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
timeIndoorTemp = timeIndoorTemp.currentDateTime().addSecs(300);
|
||
propertyList[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] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
}else if (name == "windchillf")
|
||
{
|
||
static QDateTime timeWindchill = QDateTime::currentDateTime().addSecs(-600);
|
||
propertyValue = round(fahrenheitToCelsius(value.toFloat()));
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, 1) and timeWindchill < QDateTime::currentDateTime())
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , QByteArray::number(qPow(propertyValue, 1.0)));
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
timeWindchill = timeWindchill.currentDateTime().addSecs(300);
|
||
propertyList[name] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
}else if (name == "winddir")
|
||
{
|
||
winddir = value.toFloat();
|
||
rotateAndSaveImage(this->inputPath, this->outputPath, (qreal)winddir);
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
|
||
}else if (name == "windspeedmph" or name == "windgustmph")
|
||
{
|
||
QString msg = "";
|
||
static QDateTime timeWind = QDateTime::currentDateTime().addSecs(-600);
|
||
quint8 windPriority = 1;
|
||
static QString msgNotif;
|
||
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
propertyValue = round(mphTokmh(value.toFloat()));
|
||
for (quint8 i=0; i<forceVent.size();i++)
|
||
{
|
||
if (propertyValue <= forceVent[i][0].toDouble())
|
||
{
|
||
msg = forceVent[i][1].toString();
|
||
windPriority = forceVent[i][1].toUInt();
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (propertyList["forcevent"].toString() != msg or propertyList["rafales"].toString() != msg)
|
||
{
|
||
if (name == "windspeedmph")
|
||
{
|
||
propertyList["forcevent"] = msg;
|
||
msg.prepend("Vent - ");
|
||
}else
|
||
{
|
||
propertyList["rafales"] = msg;
|
||
msg.prepend("Rafales - ");
|
||
}
|
||
msgNotif = formatNotifString (msg, propertyName[name].second , QByteArray::number(propertyValue));
|
||
setPriority(priority, windPriority);
|
||
|
||
propertyList["winddir"] = winddir;
|
||
attachment = this->outputPath;
|
||
if (priority > 3)
|
||
{
|
||
notify(msgNotif, priorityList[priority], attachment);
|
||
}else if (timeWind < QDateTime::currentDateTime() or propertyValue > 20)
|
||
{
|
||
timeWind = timeWind.currentDateTime().addSecs(300);
|
||
changed = true;
|
||
}
|
||
|
||
debug (DEBUGMACRO, "Notif = *" + notif + "*", DEBUG);
|
||
}
|
||
notif += msgNotif;
|
||
|
||
/*}else if (name == "windgustmph")
|
||
{
|
||
propertyValue = round(mphTokmh(pair.second.toFloat()));
|
||
if (compare (propertyList[name], propertyValue, 5) and propertyValue > 20)
|
||
{
|
||
notif += formatNotifString (propertyName[name].first, propertyName[name].second , QByteArray::number(propertyValue));
|
||
if (propertyValue > 40)
|
||
priority = setPriority (priority, 4);
|
||
if (propertyValue > 60)
|
||
priority = setPriority (priority, 5);
|
||
propertyList[name] = propertyValue;
|
||
debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
}*/
|
||
}else if (name == "rainin")
|
||
{
|
||
static double ecart;
|
||
propertyValue = pair.second.toFloat();
|
||
if (propertyValue == 0)
|
||
{
|
||
ecart = 0.0001;
|
||
}else
|
||
{
|
||
ecart = 0.01;
|
||
}
|
||
debug (DEBUGMACRO, name + " : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, ecart))
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , value);
|
||
QString pluviosite = getPluviosite(propertyValue);
|
||
priority = setPriority (priority, 4);
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
propertyList[name] = pluviosite + " : " + QString::number(round(propertyValue*100)/100);
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
}else if (name == "dailyrainin")
|
||
{
|
||
static double ecart;
|
||
propertyValue = pair.second.toFloat();
|
||
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] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
}else if (name == "baromin")
|
||
{
|
||
//static QDateTime timePrevision = QDateTime::currentDateTime().addSecs(-1000);
|
||
|
||
propertyValue = tohPa(pair.second.toFloat());
|
||
debug (DEBUGMACRO, "Barometre en hPa : " + QByteArray::number(propertyValue), DEBUG);
|
||
if (compare (propertiesValue[name], propertyValue, 0.5))
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second , QByteArray::number(propertyValue));
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
propertyList[name] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
changed = true;
|
||
}
|
||
|
||
static QString prevision;
|
||
QString ret = pressureVariation(propertyValue, priority);
|
||
if (!ret.isEmpty())
|
||
{
|
||
debug (DEBUGMACRO, "baromin ret not empty : " + ret, DEBUG);
|
||
QString newPrevision = ret;
|
||
priority = setPriority(priority, priority);
|
||
if (prevision != newPrevision)
|
||
{
|
||
prevision = newPrevision;
|
||
propertyList["prevision"] = prevision;
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
//changed = true;
|
||
}
|
||
}
|
||
notif += prevision + " \n";
|
||
}else if (name == "UV")
|
||
{
|
||
static QDateTime timeUV = QDateTime::currentDateTime().addSecs(-600);
|
||
propertyValue = pair.second.toFloat();
|
||
|
||
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, 3);
|
||
if (propertyValue >= 6 )
|
||
priority = setPriority (priority, 4);
|
||
timeUV = timeUV.currentDateTime().addSecs(300);
|
||
propertyList[name] = propertyValue;
|
||
propertiesValue[name] = propertyValue;
|
||
debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
}
|
||
}/*else if (name == "lowbat")
|
||
{
|
||
static QDateTime timeLowBat = QDateTime::currentDateTime().addSecs(-4000);
|
||
if (pair.second.toInt() == 0 and timeLowBat < QDateTime::currentDateTime())
|
||
{
|
||
//notif += formatNotifString (propertyName[name].first, propertyName[name].second );
|
||
//debug (DEBUGMACRO, "Notif = #" + notif + "#", DEBUG);
|
||
priority = setPriority (priority, 4);
|
||
timeLowBat = timeLowBat.currentDateTime().addSecs(3600);
|
||
propertyList[name] = propertyValue;
|
||
}
|
||
}*/
|
||
}
|
||
}
|
||
if (!jsonString.isEmpty())
|
||
{
|
||
debug(DEBUGMACRO, "json string : " + jsonString, DEBUG);
|
||
jsonString = jsonString +", " + deviceString + "}}";
|
||
mqttClient->send_message(jsonString);
|
||
}else
|
||
{
|
||
debug(DEBUGMACRO, "No values to send", DEBUG);
|
||
}
|
||
|
||
if (changed)
|
||
{
|
||
debug(DEBUGMACRO, "looping to fill notif", DEBUG);
|
||
for (auto [name, value]: propertyList.asKeyValueRange())
|
||
{
|
||
QString unit;
|
||
QByteArray valueBA;
|
||
debug(DEBUGMACRO, "Name = " + name + ", value = " + QString::number(value.toUInt()), DEBUG);
|
||
if (! propertyName.contains(name))
|
||
{
|
||
unit = "";
|
||
debug(DEBUGMACRO, "unit is empty ", DEBUG);
|
||
}else
|
||
{
|
||
unit = propertyName[name].second;
|
||
debug(DEBUGMACRO, "unit : " + unit, DEBUG);
|
||
QString dataType = value.typeName();
|
||
debug(DEBUGMACRO, "datatype is : " + dataType, DEBUG);
|
||
if (dataType == "double")
|
||
{
|
||
debug(DEBUGMACRO, "datatype is 'double'", DEBUG);
|
||
valueBA = QByteArray::number(round(value.toFloat()*100)/100);
|
||
}else if (dataType == "QString")
|
||
{
|
||
debug(DEBUGMACRO, "datatype is 'QString'" + value.toString(), DEBUG);
|
||
valueBA = value.toByteArray();
|
||
}else
|
||
{
|
||
debug(DEBUGMACRO, "datatype is null" + QString::number(value.toUInt()), DEBUG);
|
||
valueBA = value.toByteArray();
|
||
}
|
||
notif += formatNotifString(propertyName[name].first, unit, valueBA);
|
||
}
|
||
}
|
||
debug(DEBUGMACRO, "calling notify with notif = #" + notif + "#", DEBUG);
|
||
notify (notif, priorityList[priority], attachment);
|
||
}
|
||
debug(DEBUGMACRO, "parseData: Returning", DEBUG);
|
||
}
|
||
|
||
QString getPluviosite(double value)
|
||
{
|
||
if (value < 1)
|
||
{
|
||
return "Pluie fine, bruine";
|
||
}else if (value < 5)
|
||
{
|
||
return "Pluie Modérée";
|
||
}else if (value < 15)
|
||
{
|
||
return "Pluie forte";
|
||
}else if (value > 30)
|
||
{
|
||
return "Évènement extrème";
|
||
}else if (value > 15)
|
||
{
|
||
return "Forte pluie";
|
||
}
|
||
}
|
||
|
||
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 <= 1010.0)
|
||
{
|
||
priority = 4;
|
||
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)
|
||
{
|
||
CURL *curl;
|
||
CURLcode res;
|
||
std::string readBuffer;
|
||
|
||
priority = "Priority: " + priority;
|
||
debug (DEBUGMACRO, "notifying at priority " + priority + " - 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, "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);
|
||
}
|
||
}
|