From 91259485ba3411f1793148b3f22acdf3f3c0a27f Mon Sep 17 00:00:00 2001 From: Daniel TARTAVEL Date: Thu, 16 Oct 2025 17:46:29 +0200 Subject: [PATCH] suite --- httpserver.h | 14 - main.cpp | 128 -------- mqtt.cpp | 142 --------- mqtt.h | 191 ----------- pws2mqtt.cpp | 778 --------------------------------------------- pws2mqtt.h | 68 ---- utcicalculator.cpp | 178 ----------- utcicalculator.h | 44 --- version.h | 8 - 9 files changed, 1551 deletions(-) delete mode 100644 httpserver.h delete mode 100644 main.cpp delete mode 100644 mqtt.cpp delete mode 100644 mqtt.h delete mode 100644 pws2mqtt.cpp delete mode 100644 pws2mqtt.h delete mode 100644 utcicalculator.cpp delete mode 100644 utcicalculator.h delete mode 100644 version.h diff --git a/httpserver.h b/httpserver.h deleted file mode 100644 index 531aeea..0000000 --- a/httpserver.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef HTTPSERVER_H -#define HTTPSERVER_H - -#include - -class HttpServer : QObject -{ - Q_OBJECT - public: - int port = 5000; -}; - - -#endif // HTTPSERVER_H diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 32730f9..0000000 --- a/main.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pws2mqtt.h" -#include "mqtt.h" -#include "version.h" -#include -#include -#include -#include -#include "utcicalculator.h" - -#define CLIENT_ID "Client_ID" -#define BROKER_ADDRESS "localhost" -#define MQTT_PORT 1883; - -uint debugLevel = DEBUG | INFO | NOTICE | INFO | WARNING | ERROR | ALERT; -QByteArray toFollow; - -//class MqttClient; - -using namespace std; - -//Configuration config; -Pws2mqtt *pws2mqtt; -MqttClient *mqttClient; -QHttpServer *httpServer; - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - - if (argc > 1) - { - if (strcmp(argv[1], "v")) - { - printf ("Version : %s\n", version.c_str()); - exit(0); - } - } - // Enable logging to journald - qputenv("QT_FORCE_STDERR_LOGGING", QByteArray("0")); - - debug(DEBUGMACRO, "declaration of mqttClient", DEBUG); - mqttClient = new MqttClient; - - httpServer = new QHttpServer; - - //declaration of debug level - pws2mqtt = new Pws2mqtt; - - pws2mqtt->listeningHttp(); - //notify (QString("Program started"), "default"); - a.exec(); - - mqttClient->qmqttClient->unsubscribe(mqttClient->topic); - mqttClient->qmqttClient->disconnectFromHost(); - debug(DEBUGMACRO, "exiting", DEBUG); - notify ("Program exiting \n", "high"); - //Closing http server -} - -/*QString addValue(QByteArray value) -{ - bool ok; - QString str; - - value.toFloat(&ok); - if (ok) - { - str = (value); - }else - { - str = ("\"" + value + "\"" ); - } - return str; -}*/ - -void debug(QString debugHeader, QString msg, uint8_t level, QByteArray property) -{ - - msg.replace("\n", "\\n"); - if ((debugLevel & level) == 1) - { - qInfo("%s%sINFO: %s%s", debugHeader.toStdString().c_str(), GREEN, msg.toStdString().c_str(), NORMAL); - } - if ((debugLevel & level) == 2) - { - qInfo("%s%s NOTICE: %s%s", debugHeader.toStdString().c_str(), GREEN, msg.toStdString().c_str(), NORMAL); - } - if ((debugLevel & level) == 4) - { - qInfo("%s%s WARNING: %s%s", debugHeader.toStdString().c_str(), ORANGE, msg.toStdString().c_str(), NORMAL); - notify (debugHeader + " - " + msg); - } - if ((debugLevel & level) == 8) - { - qInfo("%s%s ERROR: %s%s", debugHeader.toStdString().c_str(), RED, msg.toStdString().c_str(), NORMAL); - notify ("Program error : " + debugHeader + " - " + msg, "high"); - exit(1); - } - if ((debugLevel & level) == 16) - { - qInfo("%s%s DEBUG: %s%s", debugHeader.toStdString().c_str(), GREEN, ("'" + msg.toStdString() + "'").c_str(), NORMAL); - } - if ((debugLevel & level) == 32) - { - qInfo("%s%s ALERT: %s%s", debugHeader.toStdString().c_str(), RED, msg.toStdString().c_str(), NORMAL); - notify ("Program exiting " + debugHeader + " - " + msg, "high" ); - exit(2); - } - if (toFollow == property and !toFollow.isEmpty()) - { - qInfo("%s%s FOLLOWING %s => %s%s", debugHeader.toStdString().c_str(), GREEN, property.toStdString().c_str(), msg.toStdString().c_str(), NORMAL); - } -} diff --git a/mqtt.cpp b/mqtt.cpp deleted file mode 100644 index 720fbac..0000000 --- a/mqtt.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "mqtt.h" -#include "pws2mqtt.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -extern MqttClient *mqttClient; - -MqttClient::MqttClient() -{ - // init mqtt connexion to server - debug(DEBUGMACRO, "declaration of qmqttClient", DEBUG); - this->qmqttClient = new QMqttClient(this); - - debug(DEBUGMACRO, "setting hostname of mqtt server", DEBUG); - this->qmqttClient->setHostname(this->server); - debug(DEBUGMACRO, "setting port of mqtt server", DEBUG); - this->qmqttClient->setPort(this->serverPort); //this->serverPort); - - debug(DEBUGMACRO, "Connecting 'messageReceived'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::messageReceived, this, &MqttClient::on_message); - debug (DEBUGMACRO, "Connecting 'disconnect'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::disconnected, this, &MqttClient::on_disconnect); - debug (DEBUGMACRO, "Connecting 'connected'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::connected, this, &MqttClient::on_connect); - debug (DEBUGMACRO, "Connecting 'errorChanged", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::errorChanged, this, &MqttClient::on_error); - debug (DEBUGMACRO, "Connecting 'messageSent'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::messageSent, this, &MqttClient::on_messageSent); - debug (DEBUGMACRO, "Connecting 'messageStatusChanged'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::messageStatusChanged, this, &MqttClient::on_messageSentStatusChanged); - debug (DEBUGMACRO, "Connecting 'stateChanged'", DEBUG); - QObject::connect(this->qmqttClient, &QMqttClient::stateChanged, this, &MqttClient::on_stateChanged); - -// qmqttClient->setClientId("pws2mqtt"); -// qmqttClient->setProtocolVersion(QMqttClient::MQTT_3_1_1); - - debug(DEBUGMACRO, "connecting to mqtt server", DEBUG); - this->qmqttClient->connectToHost(); - - //debug(DEBUGMACRO, "error status => " + this->qmqttErrors[this->qmqttClient->error()], DEBUG); -} - -MqttClient::~MqttClient() -{ -} - -qint32 MqttClient::send_message(QString message) -{ - qint32 mid; - - debug(DEBUGMACRO, "send_message() for topic: " + this->topic + " => " + message , DEBUG); - mid = this->qmqttClient->publish(this->topic, message.toUtf8(), this->qos, true); - if (mid == -1) - { - debug("MQTT", "Erreur, impossiblité d'envoyer le message : " + this->qmqttErrors[this->qmqttClient->error()], WARNING); - } - messagesList.insert(mid, message); - return (mid); -} - -void MqttClient::on_connect() -{ - //this->connected = true; - debug(DEBUGMACRO, "Connected to broker", DEBUG); - this->subscription = this->qmqttClient->subscribe(this->topic, this->qos); - debug (DEBUGMACRO, "Connecting sign 'subscription state Changed'", DEBUG); - QObject::connect(this->subscription, &QMqttSubscription::stateChanged, mqttClient, &MqttClient::updateStatus); -} - -void MqttClient::on_messageSentStatusChanged(qint32 id, QMqtt::MessageStatus s, const QMqttMessageStatusProperties &properties) -{ - (void) properties; - - if ( id == 0) - { - debug(DEBUGMACRO, "message id = " + QString::number(id) + this->messageStatus[static_cast(s)], INFO); - } -} - -void MqttClient::on_error(QMqttClient::ClientError error) -{ - debug("MQTT", "Error " + qmqttErrors[error], WARNING); -} - -void MqttClient::on_message(const QByteArray &message, const QMqttTopicName &topic) -{ - (void) message; - (void) topic; - debug(DEBUGMACRO, "Message : " + message, DEBUG); -} - -void MqttClient::on_disconnect() -{ - debug(DEBUGMACRO, "Unexpected disconnect", DEBUG); - this->qmqttClient->connectToHost(); -} - - -void MqttClient::on_messageSent(int mid) -{ - debug(DEBUGMACRO, "published(" + QString::number(mid) + ")", DEBUG); - messagesList.remove(mid); -} - -void MqttClient::updateStatus(QMqttSubscription::SubscriptionState state) -{ - switch (state) - { - case QMqttSubscription::Unsubscribed: - debug("MQTT", "Unsubscribed", WARNING); - break; - case QMqttSubscription::SubscriptionPending: - debug("MQTT", "Pending subscription", WARNING); - break; - case QMqttSubscription::Subscribed: - debug(DEBUGMACRO, "Subscribed", INFO); - break; - case QMqttSubscription::Error: - debug("MQTT", "Subscription error" + this->subscription->reason(), WARNING); - break; - case QMqttSubscription::UnsubscriptionPending: - debug("MQTT", "Pending Unsubscription", WARNING); - break; - default: - debug(DEBUGMACRO, "--Unknown--", DEBUG); - break; - } -} - -void MqttClient::on_stateChanged(QMqttClient::ClientState state) -{ - debug("MQTT", QLatin1String("State Change : ") + this->clientStateString[state], WARNING ); -} diff --git a/mqtt.h b/mqtt.h deleted file mode 100644 index f4afff8..0000000 --- a/mqtt.h +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef MQTT_H -#define MQTT_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MQTT_TOPIC "pws2mqtt" - - -/*{128, "Unspecified error: The Server does not wish to reveal the reason for the failure, or none of the other Reason Codes apply."}, -{129, "Malformed Packet; Data within the CONNECT packet could not be correctly parsed."}, -{130, "Protocol Error: Data in the CONNECT packet does not conform to this specification."}, -{131, "Implementation specific error: The CONNECT is valid but is not accepted by this Server."}, -{132, "Unsupported Protocol Version: The Server does not support the version of the MQTT protocol requested by the Client."}, -{133, "Client Identifier not valid: The Client Identifier is a valid string but is not allowed by the Server."}, -{134, "Bad User Name or Password: The Server does not accept the User Name or Password specified by the Client."}, -{135, "Not authorized: The Client is not authorized to connect."}, -{136, "Server unavailable: The MQTT Server is not available."}, -{137, "Server busy: The Server is busy. Try again later."}, -{138, "Banned: This Client has been banned by administrative action. Contact the server administrator."}, -{140, "Bad authentication method: The authentication method is not supported or does not match the authentication method currently in use."}, -{144, "Topic Name invalid: The Will Topic Name is not malformed, but is not accepted by this Server."}, -{149, "Packet too large: The CONNECT packet exceeded the maximum permissible size."}, -{151, "Quota exceeded: An implementation or administrative imposed limit has been exceeded."}, -{153, "Payload format invalid: The Will Payload does not match the specified Payload Format Indicator."}, -{154, "Retain not supported: The Server does not support retained messages, and Will Retain was set to 1."}, -{155, "QoS not supported: The Server does not support the QoS set in Will QoS."}, -{156, "Use another server: The Client should temporarily use another server."}, -{157, "Server moved: The Client should permanently use another server."}, -{159, "Connection rate exceeded: The connection rate limit has been exceeded."}, - - -QHash mosq_error -{ - {MOSQ_ERR_ERRNO, "System return error"}, - {MOSQ_ERR_INVAL, "Input parameters were invalid."}, - {MOSQ_ERR_NOMEM, "Out of memory condition occurred."}, - {MOSQ_ERR_PAYLOAD_SIZE, "Payloadlen is too large."}, - {MOSQ_ERR_MALFORMED_UTF8, "The topic is not valid UTF-8."}, - {MOSQ_ERR_NOT_SUPPORTED, "Properties is not NULL and the client is not using MQTT v5"}, - {MOSQ_ERR_NO_CONN, "if the client isn’t connected to a broker."}, - {MOSQ_ERR_DUPLICATE_PROPERTY, "A property is duplicated where it is forbidden."}, - {MOSQ_ERR_PROTOCOL, "Any property is invalid for use with DISCONNECT."}, - {MOSQ_ERR_QOS_NOT_SUPPORTED, "The QoS is greater than that supported by the broker."}, - {MOSQ_ERR_OVERSIZE_PACKET, "The resulting packet would be larger than supported by the broker."}, - {MOSQ_ERR_CONN_LOST, "The connection to the broker was lost."}, - {MOSQ_ERR_PROTOCOL, "There is a protocol error communicating with the broker."}, -}; -*/ - -/*class MqttSub : public QMqttSubscription -{ - Q_OBJECT; - - - - public: - explicit MqttSub(); - ~MqttSub(); - - public slots: - void updateStatus({ , "SubscriptionState state); - -};*/ - -class MqttClient : public QObject -{ - Q_OBJECT - - public: - MqttClient (); - ~MqttClient(); - - QString topic = "pws2mqtt/wh2650a"; - QString host = "127.0.0.1"; - QString friendlyName = "WH2650A"; // friendly name of the device in mqtt - QString macAddress = "0x483fda53cbcb"; // lan mac address as lan identity TODO get from device - QString type = "Meteo"; - int qos = 0; - QString server = "127.0.0.1"; //"127.0.0.1"; - int serverPort = 1883; - int keepAlive = 60; - int protocolVersion = 4; - int retryConnectionDelay = 10; // in seconds - int retrySubscribeDelay = 10; // in seconds - QMqttClient *qmqttClient; - - QHash messagesList; - QMqttSubscription *subscription = nullptr; - QMqttSubscription::SubscriptionState subscriptionState; - QMqttClient::ClientState clientState; - - qint32 send_message(QString message); - - QHash messageStatus = - { - {0, "Unknown : The message status is unknown."}, - {1, "Published : The client received a message for one of its subscriptions. This applies to QoS levels 1 and 2."}, - {2, "Acknowledged A message has been acknowledged. This applies to QoS 1 and states that the message handling has been finished from the client side."}, - {3, "Received : A message has been received. This applies to QoS 2."}, - {4, "Released : A message has been released. This applies to QoS 2. For a publisher the message handling has been finished."}, - {5, "Completed : A message has been completed. This applies to QoS 2 and states that the message handling has been finished from the client side."} - }; - - QHash connectReasonCode = - { - {0, "SubscriptionQoSLevel0 : subscription with QoS level 0 has been created."}, - {1 , "SubscriptionQoSLevel1 0x01 A subscription with QoS level 1 has been created."}, - {2 , "SubscriptionQoSLevel2 0x02 A subscription with QoS level 2 has been created."}, - {16 , "NoMatchingSubscriber 0x10 The message has been accepted by the server, but there are no subscribers to receive this message. A broker may send this reason code instead of Success."}, - {17 , "NoSubscriptionExisted (since Qt 5.15) 0x11 No matching Topic Filter is being used by the Client."}, - {24 , "ContinueAuthentication (since Qt 5.15) 0x18 Continue the authentication with another step."}, - {25 , "ReAuthenticate (since Qt 5.15) 0x19 Initiate a re-authentication."}, - {128 , "UnspecifiedError 0x80 An unspecified error occurred."}, - {129 , "MalformedPacket 0x81 The packet sent to the server is invalid."}, - {130 , "ProtocolError 0x82 A protocol error has occurred. In most cases, this will cause the server to disconnect the client."}, - {131 , "ImplementationSpecificError 0x83 The packet is valid, but the recipient rejects it."}, - {132 , "UnsupportedProtocolVersion 0x84 The requested protocol version is not supported by the server."}, - {133 , "InvalidClientId 0x85 The client ID is invalid."}, - {134 , "InvalidUserNameOrPassword 0x86 The username or password specified is invalid."}, - {135 , "NotAuthorized 0x87 The client is not authorized for the specified action."}, - {136 , "ServerNotAvailable 0x88 The server to connect to is not available."}, - {137 , "ServerBusy 0x89 The server to connect to is not available. The client is asked to try at a later time."}, - {138 , "ClientBanned 0x8A The client has been banned from the server."}, - {139 , "InvalidAuthenticationMethod 0x8C The authentication method specified is invalid."}, - {143 , "InvalidTopicFilter 0x8F The topic filter specified is invalid."}, - {144 , "InvalidTopicName 0x90 The topic name specified is invalid."}, - {145 , "MessageIdInUse 0x91 The message ID used in the previous packet is already in use."}, - {146 , "MessageIdNotFound 0x92 The message ID used in the previous packet has not been found."}, - {149 , "PacketTooLarge 0x95 The packet received is too large. See also QMqttServerConnectionProperties::maximumPacketSize()."}, - {151 , "QuotaExceeded 0x97 An administratively imposed limit has been exceeded."}, - {153 , "InvalidPayloadFormat 0x99 The payload format is invalid. See also QMqttPublishProperties::payloadFormatIndicator()."}, - {154 , "RetainNotSupported 0x9A The server does not support retained messages. See also QMqttServerConnectionProperties::retainAvailable()."}, - {155 , "QoSNotSupported 0x9B The QoS level requested is not supported. See also QMqttServerConnectionProperties::maximumQoS()."}, - {156 , "UseAnotherServer 0x9C The server the client tries to connect to is not available. See also QMqttServerConnectionProperties::serverReference()."}, - {157 , "ServerMoved 0x9D The server the client tries to connect to has moved to a new address. See also QMqttServerConnectionProperties::serverReference()."}, - {158 , "SharedSubscriptionsNotSupported 0x9E Shared subscriptions are not supported. See also QMqttServerConnectionProperties::sharedSubscriptionSupported()."}, - {159 , "ExceededConnectionRate 0x9F The connection rate limit has been exceeded."}, - {161 , "SubscriptionIdsNotSupported 0xA1 Subscription IDs are not supported. See also QMqttServerConnectionProperties::subscriptionIdentifierSupported()."}, - {162 , "WildCardSubscriptionsNotSupported 0xA2 Subscriptions using wildcards are not supported by the server. See also QMqttServerConnectionProperties::wildcardSupported()."}, - }; - - QHash qmqttErrors = - { - {1, "InvalidProtocolVersion : The broker does not accept a connection using the specified protocol version."}, - {2, "IdRejected ; The client ID is malformed. This might be related to its length."}, - {3, "ServerUnavailable :The network connection has been established, but the service is unavailable on the broker side."}, - {4, "QMqttClient::Bad Username Or Password : The data in the username or password is malformed."}, - {5, "NotAuthorized : The client is not authorized to connect."}, - {256, "TransportInvalid : The underlying transport caused an error. For example, the connection might have been interrupted unexpectedly."}, - {257, "ProtocolViolation : The client encountered a protocol violation, and therefore closed the connection."}, - {258, "UnknownError : An unknown error occurred."}, - {259, "Mqtt5SpecificError : The error is related to MQTT protocol level 5. A reason code might provide more details."} - }; - - QHash clientStateString - { - {0, "Disconnected : The client is disconnected from the broker."}, - {1, "Connecting : A connection request has been made, but the broker has not approved the connection yet."}, - {2, "Connected : The client is connected to the broker."} - }; - - QHash subscriptionStateString - { - {0, "Unsubscribed : The topic has been unsubscribed from."}, - {1, "SubscriptionPending : A request for a subscription has been sent, but is has not been confirmed by the broker yet."}, - {2, "Subscribed : The subscription was successful and messages will be received."}, - {3, "UnsubscriptionPending : A request to unsubscribe from a topic has been sent, but it has not been confirmed by the broker yet."}, - {4, "Error : An error occured."} - }; - - public slots: - void on_message(const QByteArray &message, const QMqttTopicName &topic); - void on_connect(); - void on_disconnect(); - void on_error(QMqttClient::ClientError error); - void on_messageSentStatusChanged(qint32 id, QMqtt::MessageStatus s, const QMqttMessageStatusProperties &properties); - void on_messageSent(int mid); - void updateStatus(QMqttSubscription::SubscriptionState state); - void on_stateChanged(QMqttClient::ClientState state); -// void updateMessage(); -}; - - -#endif //MQTT_H diff --git a/pws2mqtt.cpp b/pws2mqtt.cpp deleted file mode 100644 index a998132..0000000 --- a/pws2mqtt.cpp +++ /dev/null @@ -1,778 +0,0 @@ -#include "pws2mqtt.h" -#include "mqtt.h" -//#include "httpserver.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "utcicalculator.h" - -extern MqttClient *mqttClient; -extern Pws2mqtt *pws2mqtt; -extern QHttpServer *httpServer; -UtciCalculator calc; - -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 propertyList; -QMap precPropertyList; -QMap propertiesValue; -QMap > 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 > 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> 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> 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> 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 = ""; - 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 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 == "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] = 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" or name == "windgustmph") - { - QString msg = ""; - 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 (quint8 i=0; ioutputPath; - } - }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; - } - }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; - } - }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] = formatNotifString(propertyName[name].first, "", QByteArray::number(propertyValue)); - propertiesValue[name] = propertyValue; - } - - static QString prevision; - quint8 prevPriority = 0; - QString ret = pressureVariation(propertyValue, prevPriority); - if (!ret.isEmpty()) - { - debug (DEBUGMACRO, "baromin ret not empty : " + ret, DEBUG); - QString newPrevision = ret; - priority = setPriority(priority, prevPriority); - if (prevision != newPrevision) - { - prevision = newPrevision; - propertyList["prevision"] = "- " + 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, 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); - } - }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); - notif += propertyList[name]; - } - debug(DEBUGMACRO, "calling notify with notif = #" + notif + "#", DEBUG); - if (changed) - { - notify (notif, priorityList[priority], attachment); - 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 <= 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 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); - } -} diff --git a/pws2mqtt.h b/pws2mqtt.h deleted file mode 100644 index 8f15cbc..0000000 --- a/pws2mqtt.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef PWS2MQTT_H -#define PWS2MQTT_H - -#include -#include -#include -#include -#include - -#define RED "\e[31m" -#define GREEN "\e[32m" -#define BLUE "\e[94m" -#define ORANGE "\e[33m" -#define NORMAL "\e[0m" - -#define DEBUG 16 // => 16 -#define INFO 1 // => 1 -#define NOTICE 2 // => 2 -#define WARNING 4 // => 4 -#define ERROR 8 // => 8 -#define ALERT 32 -#define ALL DEBUG | INFO | NOTICE | WARNING | ERROR | ALERT -#define DEBUGMACRO QString(__FILE__) + ": " + QString::number(__LINE__) + " -> " - -void debug(QString debugHeader, QString msg, uint8_t level=ALL, QByteArray value=""); -//QString addValue(QByteArray value); - -class Pws2mqtt : public QObject -{ - Q_OBJECT - - public: - Pws2mqtt(); - ~Pws2mqtt(); - - QString ProcName = "pws2mqtt"; // name of the proceesus in ps, top, pstree, ...; - FILE * logFh = nullptr; - QString listenHost = "0.0.0.0"; - uint listenPort = 5000; - int sockfd = 0; - int newsockfd = 0; - QString inputPath = "/usr/local/share/pws2mqtt/fleche.png"; - QString outputPath = "/tmp/pws2mqttFleche.png"; - QList deviceProperties = - { - "ieeeAddress", "type", "dateutc", "softwaretype", "action", "realtime", "freq", "wh65batt", "wh25batt", "runtime" - }; - - void init(); - void listeningHttp(); - void parseData(QList> queryList); -}; - -double fahrenheitToCelsius(double fahrenheit); -double tohPa(double value); -bool compare (double value=0, double testValue=0, double ecart = 0.5); -QString formatNotifString (QString name, QString unit, QByteArray value=""); -double mphTokmh (double value); -void notify (QString notif, QString priority = "low", QString inputPath = ""); -quint8 setPriority (quint8 currentPriority, quint8 newPriority); -QString previsionMeteo(double currentPressure, double variation3h, quint8 &priority); -QString pressureVariation(double currentPressure, quint8 &priority); -QString getPluviosite(double value, quint8 &priority); -void rotateAndSaveImage(const QString &inputPath, const QString &outputPath, qreal angle=0); -double windChill(double airT, double vent); -double calculerHumidex(double temperature, double humiditeRelative); - -#endif // PWS2MQTT_H diff --git a/utcicalculator.cpp b/utcicalculator.cpp deleted file mode 100644 index 6449985..0000000 --- a/utcicalculator.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "utcicalculator.h" -#include -#include -#include -#include - -UtciCalculator::UtciCalculator(QObject *parent) - : QObject(parent) -{ -} - -/*// Loads coefficients from a simple text file containing one coefficient per line or tab-separated. -// The expected file is the ESM_3 coefficients table exported to a plain text file where the coefficients -// appear in the same order as in the official table (210 coefficients). -bool UtciCalculator::loadCoefficientsFromFile(const QString &path) -{ - QFile f(path); - if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) - return false; - - QTextStream in(&f); - QVector coeffs; - coeffs.reserve(300); - - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - if (line.isEmpty()) continue; - // Allow lines with comments or 'term coefficient' headings: - // We try to extract numbers from the line. - QStringList parts = line.split(QRegularExpression("[\\s,\\t]+"), Qt::SkipEmptyParts); - for (const QString &p : parts) { - bool ok = false; - double val = p.toDouble(&ok); - if (ok) coeffs.append(val); - } - } - if (coeffs.isEmpty()) return false; - - m_coeffs = coeffs; - return true; -} -*/ -// Magnus formula to estimate saturation vapour pressure (hPa) then return pa in kPa -double UtciCalculator::vapourPressureFromRH(double Ta, double rh) -{ - // Magnus-Tetens approximation for saturation vapour pressure (hPa) - // valid roughly for -45C..+60C - // constants for water over liquid - double a = 17.27; - double b = 237.7; // °C - double es = 6.112 * qExp((a * Ta) / (Ta + b)); - double ea = es * (rh / 100.0); - return ea / 10.0; // hPa -> kPa -} - -double UtciCalculator::computeUTCI(double Ta, double va, double Tr, double rh) const -{ - double pa = vapourPressureFromRH(Ta, rh); - double tm = Tr - Ta; - double offset = evalOffset(Ta, va, tm, pa); - return Ta + offset; -} - -double UtciCalculator::evalOffset(double Ta, double va, double tm, double pa) const -{ - if (m_coeffs.size() < 210) - return 0.0; - - // Pré-calcul des puissances - double Ta2 = Ta*Ta, Ta3 = Ta2*Ta, Ta4 = Ta3*Ta, Ta5 = Ta4*Ta, Ta6 = Ta5*Ta; - double va2 = va*va, va3 = va2*va, va4 = va3*va, va5 = va4*va, va6 = va5*va; - double tm2 = tm*tm, tm3 = tm2*tm, tm4 = tm3*tm, tm5 = tm4*tm, tm6 = tm5*tm; - double pa2 = pa*pa, pa3 = pa2*pa, pa4 = pa3*pa, pa5 = pa4*pa, pa6 = pa5*pa; - - QVector terms(210, 0.0); - - // Construire les termes dans le même ordre que les coefficients ESM_3 - terms[0] = 1.0; // constante - terms[1] = Ta; - terms[2] = Ta2; - terms[3] = Ta3; - terms[4] = Ta4; - terms[5] = Ta5; - terms[6] = Ta6; - - terms[7] = va; - terms[8] = Ta*va; - terms[9] = Ta2*va; - terms[10] = Ta3*va; - terms[11] = Ta4*va; - terms[12] = Ta5*va; - - terms[13] = va2; - terms[14] = Ta*va2; - terms[15] = Ta2*va2; - terms[16] = Ta3*va2; - terms[17] = Ta4*va2; - - terms[18] = va3; - terms[19] = Ta*va3; - terms[20] = Ta2*va3; - terms[21] = Ta3*va3; - - terms[22] = va4; - terms[23] = Ta*va4; - terms[24] = Ta2*va4; - - terms[25] = va5; - terms[26] = Ta*va5; - - terms[27] = va6; - - terms[28] = tm; - terms[29] = Ta*tm; - terms[30] = Ta2*tm; - terms[31] = Ta3*tm; - terms[32] = Ta4*tm; - terms[33] = Ta5*tm; - terms[34] = Ta6*tm; - - terms[35] = va*tm; - terms[36] = Ta*va*tm; - terms[37] = Ta2*va*tm; - terms[38] = Ta3*va*tm; - terms[39] = Ta4*va*tm; - - terms[40] = va2*tm; - terms[41] = Ta*va2*tm; - terms[42] = Ta2*va2*tm; - terms[43] = Ta3*va2*tm; - - terms[44] = va3*tm; - terms[45] = Ta*va3*tm; - terms[46] = Ta2*va3*tm; - - terms[47] = va4*tm; - terms[48] = Ta*va4*tm; - - terms[49] = va5*tm; - - // tm^2 à tm^6 - terms[50] = tm2; terms[51] = Ta*tm2; terms[52] = Ta2*tm2; terms[53] = Ta3*tm2; terms[54] = Ta4*tm2; - terms[55] = va*tm2; terms[56] = Ta*va*tm2; terms[57] = Ta2*va*tm2; terms[58] = Ta3*va*tm2; - terms[59] = va2*tm2; terms[60] = Ta*va2*tm2; terms[61] = Ta2*va2*tm2; - terms[62] = va3*tm2; - terms[63] = tm3; terms[64] = Ta*tm3; terms[65] = Ta2*tm3; - terms[66] = va*tm3; terms[67] = Ta*va*tm3; terms[68] = va2*tm3; - terms[69] = tm4; terms[70] = Ta*tm4; terms[71] = va*tm4; - terms[72] = tm5; - terms[73] = tm6; - - // pa et combinaisons - terms[74] = pa; terms[75] = Ta*pa; terms[76] = Ta2*pa; terms[77] = Ta3*pa; terms[78] = Ta4*pa; terms[79] = Ta5*pa; - terms[80] = va*pa; terms[81] = Ta*va*pa; terms[82] = Ta2*va*pa; terms[83] = Ta3*va*pa; - terms[84] = va2*pa; terms[85] = Ta*va2*pa; terms[86] = Ta2*va2*pa; - terms[87] = va3*pa; terms[88] = Ta*va3*pa; - terms[89] = va4*pa; - - terms[90] = pa2; terms[91] = Ta*pa2; terms[92] = Ta2*pa2; - - // Remplir le reste avec 0.0 pour simplifier (les 210 coefficients réels peuvent être affectés directement) - for (int i = 93; i < 210; ++i) terms[i] = 0.0; - - // Calcul de l'offset - double offset = 0.0; - for (int i = 0; i < 210; ++i) - offset += m_coeffs[i] * terms[i]; - - return offset; -} - -void UtciCalculator::initCoefficients() -{ - // Coefficients ESM_3 (exemple simplifié, à remplacer par la liste complète 210 valeurs) - m_coeffs = { - 6.07562052E-01, -2.27712343E-02, 8.06470249E-04, -1.54271372E-04, -3.24651735E-06, 7.32602852E-08, 1.35959073E-09, -2.25836520E+00, 8.80326035E-02, 2.16844454E-03, -1.53347087E-05, -5.72983704E-07, -2.55090145E-09, -7.51269505E-01, -4.08350271E-03, -5.21670675E-05, 1.94544667E-06, 1.14099531E-08, 1.58137256E-01, -6.57263143E-05, 2.22697524E-07, -4.16117031E-08, -1.27762753E-02, 9.66891875E-06, 2.52785852E-09, 4.56306672E-04, -1.74202546E-07, -5.91491269E-06, 3.98374029E-01, 1.83945314E-04, -1.73754510E-04, -7.60781159E-07, 3.77830287E-08, 5.43079673E-10, -2.00518269E-02, 8.92859837E-04, 3.45433048E-06, -3.77925774E-07, -1.69699377E-09, 1.69992415E-04, -4.99204314E-05, 2.47417178E-07, 1.07596466E-08, 8.49242932E-05, 1.35191328E-06, -6.21531254E-09, -4.99410301E-06, -1.89489258E-08, 8.15300114E-08, 7.55043090E-04, -3.69476348E-02, 1.62325322E-03, -3.14279680E-05, 2.59835559E-06, -4.77136523E-08, 8.64203390E-03, -6.87405181E-04, -9.13863872E-06, 5.15916806E-07, -3.59217476E-05, 3.28696511E-05, -7.10542454E-07, -1.24382300E-05, -7.38584400E-09, 2.20609296E-07, -7.32469180E-04, -1.87381964E-05, 4.80925239E-06, -8.75492040E-08, 2.77862930E-05, -5.06004592E-06, 1.14325367E-07, 2.53016723E-06, -1.72857035E-08, -3.95079398E-08, -3.59413173E-07, 7.04388046E-07, -1.89309167E-08, -4.79768731E-07, 7.96079978E-09, 1.62897058E-09, 3.94367674E-08, -1.18566247E-09, 3.34678041E-10, -1.15606447E-10, -2.80626406E+00, 5.48712484E-01, -3.99428410E-03, -9.54009191E-04, 1.93090978E-05, -3.08806365E-01, 1.16952364E-02, 4.95271903E-04, -1.90710882E-05, 2.10787756E-03, -6.98445738E-04, 2.30109073E-05, 4.17856590E-04, -1.27043871E-05, -3.04620472E-06, -5.65095215E-05, -4.52166564E-07, 2.46688878E-08, 2.42674348E-10, 1.54547250E-04, 5.24110970E-06, -8.75874982E-08, -1.50743064E-09, -1.56236307E-05, -1.33895614E-07, 2.49709824E-09, 6.51711721E-07, 1.94960053E-09, -1.00361113E-08, -1.21206673E-05, -2.18203660E-07, 7.51269482E-09, 9.79063848E-11, 1.25006734E-06, -1.81584736E-09, -3.52197671E-10, -3.36514630E-08, 1.35908359E-10, 4.17032620E-10, -1.30369025E-09, 4.13908461E-10, 9.22652254E-12, -5.08220384E-09, -2.24730961E-11, 1.17139133E-10, 6.62154879E-10, 4.03863260E-13, 1.95087203E-12, -4.73602469E-12, 5.12733497E+00, -3.12788561E-01, -1.96701861E-02, 9.99690870E-04, 9.51738512E-06, -4.66426341E-07, 5.48050612E-01, -3.30552823E-03, -1.64119440E-03, -5.16670694E-06, 9.52692432E-07, -4.29223622E-02, 5.00845667E-03, 1.00601257E-06, -1.81748644E-06, -1.25813502E-03, -1.79330391E-04, 2.34994441E-06, 1.29735808E-04, 1.29064870E-06, -2.28558686E-06, 5.14507424E-02, -4.32510997E-03, 8.99281156E-05, -7.14663943E-07, -2.66016305E-04, 2.63789586E-04, -7.01199003E-06, -1.06823306E-04, 3.61341136E-06, 2.29748967E-07, 3.04788893E-04, -6.42070836E-05, 1.16257971E-06, 7.68023384E-06, -5.47446896E-07, -3.59937910E-08, -4.36497725E-06, 1.68737969E-07, 2.67489271E-08, 3.23926897E-09, -3.53874123E-02, -2.21201190E-01, 1.55126038E-02, -2.63917279E-04, 4.53433455E-02, -4.32943862E-03, 1.45389826E-04, 2.17508610E-04, -6.66724702E-05, 3.33217140E-05, -2.26921615E-03, 3.80261982E-04, -5.45314314E-09, -7.96355448E-04, 2.53458034E-05, -6.31223658E-06, 3.02122035E-04, -4.77403547E-06, 1.73825715E-06, -4.09087898E-07, 6.14155345E-01, -6.16755931E-02, 1.33374846E-03, 3.55375387E-03, -5.13027851E-04, 1.02449757E-04, -1.48526421E-03, -4.11469183E-05, -6.80434415E-06, -9.77675906E-06, 8.82773108E-02, -3.01859306E-03, 1.04452989E-03, 2.47090539E-04, 1.48348065E-03 - }; -} diff --git a/utcicalculator.h b/utcicalculator.h deleted file mode 100644 index 6d59947..0000000 --- a/utcicalculator.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include -#include - -/* - UtciCalculator - - lit un fichier de coefficients (format ESM_3/tab-delimited) - - calcule UTCI via l'approximation polynomiale : UTCI = Ta + Offset(Ta, va, tm, pa) - where tm = Tr - Ta and pa is water vapour pressure in kPa. - - fournit une fonction utilitaire pour calculer pa depuis Ta et relative humidity (Magnus-Tetens). -*/ - -class UtciCalculator : public QObject -{ - Q_OBJECT -public: - explicit UtciCalculator(QObject *parent = nullptr); - - // Load coefficients from a file (ESM_3 table or exported txt) - // Return true on success. - //bool loadCoefficientsFromFile(const QString &path); - - // Calculate UTCI. - // Ta: air temperature (°C) - // va: wind speed at 10 m (m/s) - // Tr: mean radiant temperature (°C) - // rh: relative humidity in % (0..100). If rh < 0, supply pa directly (next param) and set pa_provided=true. - // pa_kpa: vapour pressure in kPa (used if pa_provided==true) - double computeUTCI(double Ta, double va, double Tr, double rh) const; - - // Utility: compute water vapour pressure (kPa) from Ta and relative humidity (Magnus formula) - // Ta in °C, rh in % - static double vapourPressureFromRH(double Ta, double rh_percent); - -private: - // coefficients in the same order as the ESM_3 polynomial table terms. - QVector m_coeffs; - - // Evaluate the polynomial offset = f(Ta, va, tm, pa) - double evalOffset(double Ta, double va, double tm, double pa) const; - void initCoefficients(); // initialise m_coeffs avec les 210 valeurs -}; diff --git a/version.h b/version.h deleted file mode 100644 index 065e7e6..0000000 --- a/version.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#include - -std::string version = "1.0.54"; - -#endif // VERSION_H