From 1ed9d5a6740c767e7a66db1a9acc2883b7f6c3bd Mon Sep 17 00:00:00 2001 From: "de@itstall.de" <de@itstall.de> Date: Tue, 28 Jan 2020 21:24:15 +0100 Subject: [PATCH] backend listening rto requests now --- MqttClient.h | 51 ++++++++++++---------- backend.cpp | 21 ++++----- backend.vcxproj | 1 + backend.vcxproj.filters | 3 ++ dbSqlite.h | 94 ++++++++++++++++++++++++++++++----------- openweathermap.h | 42 ++++++------------ structs.h | 50 ++++++++++++++++++++++ 7 files changed, 175 insertions(+), 87 deletions(-) create mode 100644 structs.h diff --git a/MqttClient.h b/MqttClient.h index dcc37d4..7eaa94e 100644 --- a/MqttClient.h +++ b/MqttClient.h @@ -5,45 +5,52 @@ #include <cstdio> #include <mosquittopp.h> #include "dbSqlite.h" +#include "structs.h" #define MAX_PAYLOAD 50 #define DEBUG true class MqttClient : public mosqpp::mosquittopp { private: - const char* host; - const char* id; - const char* user; - const char* pass; - int port; - int keepalive; dbSqlite* db; public: - MqttClient(const char* id, const char* host, int port, const char* user, const char* pass, const char* topic) : mosquittopp(id) { - if(DEBUG) std::cout << "MqttClient::MqttClient()" << std::endl; - db = new dbSqlite(); - this->keepalive = 60; - this->id = id; - this->port = db->getSettings().mqtt_port; - this->host = db->getSettings().mqtt_host.c_str(); - this->user = db->getSettings().mqtt_user.c_str(); - this->pass = db->getSettings().mqtt_pass.c_str(); + MqttClient(const char* id_new, dbSqlite* db_new) : mosquittopp(id_new) { + if (DEBUG) std::cout << "MqttClient::MqttClient()" << std::endl; + this->db = db_new; + int keepalive = 60; + if (DEBUG) std::cout << "MqttClient: Connecting to host: " << db->getSettings().mqtt_host << std::endl; + if (DEBUG) std::cout << "MqttClient: With user: " << db->getSettings().mqtt_user << std::endl; + if (DEBUG) std::cout << "MqttClient: Backend Topic: " << db->getSettings().mqtt_topic_backend << std::endl; + if (DEBUG) std::cout << "MqttClient: Frontend Topic: " << db->getSettings().mqtt_topic_frontend << std::endl; + if (DEBUG) std::cout << "MqttClient: port: " << db->getSettings().mqtt_port << std::endl; + if (DEBUG) std::cout << "MqttClient: id: " << id_new << std::endl; + if (DEBUG) std::cout << "MqttClient: keepalive: " << keepalive << std::endl; + // Benutzername und Passwort setzen - username_pw_set(user, pass); + mosquittopp::username_pw_set(db->getSettings().mqtt_user.c_str(), db->getSettings().mqtt_pass.c_str()); + if (DEBUG) std::cout << "MqttClient: Username and password set: " << std::endl; + // Asynchrone Verbindung aufbauen - connect(host, port, keepalive); + mosquittopp::connect(db->getSettings().mqtt_host.c_str(), db->getSettings().mqtt_port, keepalive); + if (DEBUG) std::cout << "MqttClient: connect " << std::endl; + // Subscribe zu Backend Topic - subscribe(NULL, db->getSettings().mqtt_topic_backend.c_str()); + mosquittopp::subscribe(NULL, db->getSettings().mqtt_topic_backend.c_str()); + if (DEBUG) std::cout << "MqttClient: subscribe: " << std::endl; + // Startet den Thread - loop_start(); + mosquittopp::loop_start(); + if (DEBUG) std::cout << "MqttClient: loop start: " << std::endl; } ~MqttClient() { // Stoppt den Thread loop_stop(); + if (DEBUG) std::cout << "MqttClient: loop stopped: " << std::endl; // Mosuqitto library cleanup mosqpp::lib_cleanup(); + if (DEBUG) std::cout << "MqttClient: libs cleaned: " << std::endl; } void on_connect(int rc) { @@ -90,9 +97,9 @@ public: if (str.find("Request_") != std::string::npos) { std::cout << "MqttClient::on_message() - Request found" << std::endl; std::string client = str.substr(str.find("_") + 1); - std::string message = "Client " + client + " requested update"; - snprintf(buf, payload_size, message.c_str()); - publish(NULL, db->getSettings().mqtt_topic_frontend.c_str(), strlen(buf), buf); + std::cout << "Client " + client + " requested update" << std::endl; + snprintf(buf, payload_size, db->getFrontendData().c_str()); + publish(NULL, db->getSettings().mqtt_topic_frontend.c_str(), strlen(db->getFrontendData().c_str()), db->getFrontendData().c_str()); } } } diff --git a/backend.cpp b/backend.cpp index f3deedb..e9c00f7 100644 --- a/backend.cpp +++ b/backend.cpp @@ -6,20 +6,20 @@ #include "openweathermap.h" #include "MqttClient.h" #include "dbSqlite.h" +#include "structs.h" #define DEBUG true // Database object dbSqlite* db; +openweathermap* owmw; // Thread for openweathermap:getWeather void schedulerWeather(int time) { if (DEBUG) std::cout << "Wetterstation::schedulerWeather()" << std::endl; while (1) { - openweathermap owmw; - - owmw.getWeather(db->getSettings().owm_plz, db->getSettings().owm_lngCode); - Sleep(time); + owmw->getWeather(db->getSettings().owm_plz, db->getSettings().owm_lngCode); + std::this_thread::sleep_for(std::chrono::milliseconds(time)); } } @@ -27,10 +27,8 @@ void schedulerWeather(int time) { void schedulerForecast(int time) { if (DEBUG) std::cout << "Wetterstation::schedulerForecast()" << std::endl; while (1) { - openweathermap owmw; - - owmw.getForecast(db->getSettings().owm_plz, db->getSettings().owm_lngCode); - Sleep(time); + owmw->getForecast(db->getSettings().owm_plz, db->getSettings().owm_lngCode); + std::this_thread::sleep_for(std::chrono::milliseconds(time)); } } @@ -39,7 +37,7 @@ void mqttStart() { mosqpp::lib_init(); - MqttClient* mqttClient = new MqttClient("Wetterstation", db->getSettings().mqtt_host.c_str(), db->getSettings().mqtt_port, db->getSettings().mqtt_user.c_str(), db->getSettings().mqtt_pass.c_str(), db->getSettings().mqtt_topic_backend.c_str()); + MqttClient* mqttClient = new MqttClient("Wetterstation", db); mosqpp::lib_cleanup(); } @@ -59,11 +57,14 @@ int main() { // Initialisieren der Datenbank db = new dbSqlite(); + owmw = new openweathermap(db); + // Thread für getWeather starten std::thread thrWeather{ schedulerWeather, 60000 }; std::this_thread::sleep_for(std::chrono::milliseconds(50)); + // Thread für getForecast starten - std::thread thrForecast{ schedulerForecast, 900000 }; + std::thread thrForecast{ schedulerForecast, 10000 }; std::this_thread::sleep_for(std::chrono::milliseconds(50)); // MQTT starten diff --git a/backend.vcxproj b/backend.vcxproj index f54a234..9188a47 100644 --- a/backend.vcxproj +++ b/backend.vcxproj @@ -159,6 +159,7 @@ <ClInclude Include="influxdb.h" /> <ClInclude Include="json.h" /> <ClInclude Include="openweathermap.h" /> + <ClInclude Include="structs.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/backend.vcxproj.filters b/backend.vcxproj.filters index 659c0a4..1f3b277 100644 --- a/backend.vcxproj.filters +++ b/backend.vcxproj.filters @@ -43,5 +43,8 @@ <ClInclude Include="compatibility.h"> <Filter>Quelldateien</Filter> </ClInclude> + <ClInclude Include="structs.h"> + <Filter>Quelldateien</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/dbSqlite.h b/dbSqlite.h index c319d27..c56cde0 100644 --- a/dbSqlite.h +++ b/dbSqlite.h @@ -4,6 +4,8 @@ #include <vector> #include "Poco/Data/Session.h" #include "Poco/Data/SQLite/Connector.h" +#include "structs.h" +#include "nlohmann/json.hpp" using namespace Poco::Data::Keywords; using Poco::Data::Session; @@ -13,35 +15,12 @@ using std::cout; #define DEBUG false -struct WeatherConditions { - int condition_id; - std::string main; - std::string description; -}; - -struct Settings { - std::string owm_appid; - std::string owm_plz; - std::string owm_lngCode; - std::string influx_host; - int influx_port; - std::string influx_db; - std::string influx_user; - std::string influx_pass; - std::string mqtt_host; - std::string mqtt_user; - std::string mqtt_pass; - std::string mqtt_topic_frontend; - std::string mqtt_topic_backend; - int mqtt_qos; - std::string mqtt_timeout; - int mqtt_port; -}; - class dbSqlite { private: std::vector<WeatherConditions> weatherConditions; Settings settings; + std::vector<weatherData> vecForecast; + weatherData sWeather; public: string dbFile; @@ -63,6 +42,71 @@ public: return this->weatherConditions; } + weatherData getSWeather() { + return this->sWeather; + } + + std::string getFrontendData() { + nlohmann::json jObj; + + for (int i = 0; i < vecForecast.size(); i++) { + jObj["result"]["forecast"][i]["plz"] = vecForecast[i].plz; + jObj["result"]["forecast"][i]["lngCode"] = vecForecast[i].lngCode; + jObj["result"]["forecast"][i]["sunrise"] = vecForecast[i].sunrise; + jObj["result"]["forecast"][i]["sunset"] = vecForecast[i].sunset; + jObj["result"]["forecast"][i]["visibility"] = vecForecast[i].visibility; + jObj["result"]["forecast"][i]["temp"] = vecForecast[i].temp; + jObj["result"]["forecast"][i]["tempFeelsLike"] = vecForecast[i].tempFeelsLike; + jObj["result"]["forecast"][i]["tempMin"] = vecForecast[i].tempMin; + jObj["result"]["forecast"][i]["tempMax"] = vecForecast[i].tempMax; + jObj["result"]["forecast"][i]["humidity"] = vecForecast[i].humidity; + jObj["result"]["forecast"][i]["pressure"] = vecForecast[i].pressure; + jObj["result"]["forecast"][i]["windSpeed"] = vecForecast[i].windSpeed; + jObj["result"]["forecast"][i]["windDeg"] = vecForecast[i].windDeg; + jObj["result"]["forecast"][i]["clouds"] = vecForecast[i].clouds; + jObj["result"]["forecast"][i]["rain1h"] = vecForecast[i].rain1h; + jObj["result"]["forecast"][i]["rain3h"] = vecForecast[i].rain3h; + jObj["result"]["forecast"][i]["snow1h"] = vecForecast[i].snow1h; + jObj["result"]["forecast"][i]["snow3h"] = vecForecast[i].snow3h; + jObj["result"]["forecast"][i]["icons"] = vecForecast[i].icons; + jObj["result"]["forecast"][i]["from"] = vecForecast[i].from; + } + jObj["result"]["current"]["plz"] = sWeather.plz; + jObj["result"]["current"]["lngCode"] = sWeather.lngCode; + jObj["result"]["current"]["sunrise"] = sWeather.sunrise; + jObj["result"]["current"]["sunset"] = sWeather.sunset; + jObj["result"]["current"]["visibility"] = sWeather.visibility; + jObj["result"]["current"]["temp"] = sWeather.temp; + jObj["result"]["current"]["tempFeelsLike"] = sWeather.tempFeelsLike; + jObj["result"]["current"]["tempMin"] = sWeather.tempMin; + jObj["result"]["current"]["tempMax"] = sWeather.tempMax; + jObj["result"]["current"]["humidity"] = sWeather.humidity; + jObj["result"]["current"]["pressure"] = sWeather.pressure; + jObj["result"]["current"]["windSpeed"] = sWeather.windSpeed; + jObj["result"]["current"]["windDeg"] = sWeather.windDeg; + jObj["result"]["current"]["clouds"] = sWeather.clouds; + jObj["result"]["current"]["rain1h"] = sWeather.rain1h; + jObj["result"]["current"]["rain3h"] = sWeather.rain3h; + jObj["result"]["current"]["snow1h"] = sWeather.snow1h; + jObj["result"]["current"]["snow3h"] = sWeather.snow3h; + jObj["result"]["current"]["icons"] = sWeather.icons; + jObj["result"]["current"]["from"] = sWeather.from; + + return jObj.dump(); + } + + std::string getFrontendJson() { + nlohmann::json combinedjObj; + } + + void setSWeather(weatherData wd) { + this->sWeather = wd; + } + + void setSForecast(std::vector<weatherData> fc) { + this->vecForecast = fc; + } + void querySettings() { if (DEBUG) std::cout << "dbSqlite::querySettings()" << std::endl; Session session("SQLite", this->dbFile); diff --git a/openweathermap.h b/openweathermap.h index 2b1fd6a..e5e204e 100644 --- a/openweathermap.h +++ b/openweathermap.h @@ -18,32 +18,10 @@ #include "influxdb.h" #include "dbSqlite.h" #include "json.h" +#include "structs.h" #define DEBUG false -struct weatherData { - std::string plz; - std::string lngCode; - int sunrise; - int sunset; - int visibility; - double temp; - double tempFeelsLike; - double tempMin; - double tempMax; - int humidity; - int pressure; - double windSpeed; - int windDeg; - int clouds; - double rain1h; - double rain3h; - double snow1h; - double snow3h; - std::string icons; - std::string from; -}; - class openweathermap { private: std::string appid; @@ -52,10 +30,12 @@ private: weatherData sWeather; std::vector<weatherData> vecForecast; dbSqlite* db; + public: - openweathermap() { + openweathermap(dbSqlite* db_new) { if (DEBUG) std::cout << "openweathermap::openweathermap()" << std::endl; - db = new dbSqlite(); + this->db = db_new; + //db = new dbSqlite(); } std::string str_tolower(std::string s) { @@ -97,10 +77,11 @@ public: this->sWeather.snow1h = jObj["snow"]["1h"].ToFloat(); this->sWeather.snow3h = jObj["snow"]["3h"].ToFloat(); this->sWeather.icons = jObj["weather"].dump(); + db->setSWeather(this->sWeather); } void setSForecast(json::JSON jObj, std::string plz, std::string lngCode) { - if (DEBUG) std::cout << "openweathermap::setSForecast(" << plz << ")" << std::endl; + if (DEBUG) std::cout << "openweathermap::setSForecast(" << plz << ") " << jObj["cnt"] << std::endl; for (int i = 0; i < jObj["cnt"].ToInt(); i++) { weatherData item; item.plz = plz; @@ -125,6 +106,7 @@ public: this->vecForecast[i] = item; } } + db->setSForecast(this->vecForecast); } std::string getResponse(std::string url) { @@ -161,9 +143,8 @@ public: void getWeather(std::string plz, std::string lngCode) { if (DEBUG) std::cout << "openweathermap::getWeather(" << plz << ", " << lngCode << ")" << std::endl; lngCode = str_tolower(lngCode); - this->setSWeather(json::JSON::Load(this->getResponse("http://api.openweathermap.org/data/2.5/weather?zip=" + plz + "," + lngCode + "&appid=" + db->getSettings().owm_appid + "&mode=json&units=metric&lang=de")), plz, lngCode); - - if (DEBUG) std::cout << "owm_appid: " << db->getSettings().owm_appid << std::endl; + std::string url = "http://api.openweathermap.org/data/2.5/weather?zip=" + plz + "," + lngCode + "&appid=" + db->getSettings().owm_appid + "&mode=json&units=metric&lang=de"; + this->setSWeather(json::JSON::Load(this->getResponse(url)), plz, lngCode); influxdb_cpp::server_info si(db->getSettings().influx_host, db->getSettings().influx_port, db->getSettings().influx_db, db->getSettings().influx_user, db->getSettings().influx_pass); influxdb_cpp::builder() @@ -193,6 +174,7 @@ public: void getForecast(std::string plz, std::string lngCode) { if (DEBUG) std::cout << "openweathermap::getForecast(" << plz << ", " << lngCode << ")" << std::endl; lngCode = str_tolower(lngCode); - this->setSForecast(json::JSON::Load(this->getResponse("http://api.openweathermap.org/data/2.5/forecase?zip=" + plz + "," + lngCode + "&appid=" + db->getSettings().owm_appid + "&mode=json&units=metric&lang=de")), plz, lngCode); + std::string url = "http://api.openweathermap.org/data/2.5/forecast?zip=" + plz + "," + lngCode + "&appid=" + db->getSettings().owm_appid + "&mode=json&units=metric&lang=de"; + this->setSForecast(json::JSON::Load(this->getResponse(url)), plz, lngCode); } }; \ No newline at end of file diff --git a/structs.h b/structs.h new file mode 100644 index 0000000..5084c67 --- /dev/null +++ b/structs.h @@ -0,0 +1,50 @@ +#pragma once +#include <iostream> + +struct WeatherConditions { + int condition_id; + std::string main; + std::string description; +}; + +struct Settings { + std::string owm_appid; + std::string owm_plz; + std::string owm_lngCode; + std::string influx_host; + int influx_port; + std::string influx_db; + std::string influx_user; + std::string influx_pass; + std::string mqtt_host; + std::string mqtt_user; + std::string mqtt_pass; + std::string mqtt_topic_frontend; + std::string mqtt_topic_backend; + int mqtt_qos; + std::string mqtt_timeout; + int mqtt_port; +}; + +struct weatherData { + std::string plz; + std::string lngCode; + int sunrise; + int sunset; + int visibility; + double temp; + double tempFeelsLike; + double tempMin; + double tempMax; + int humidity; + int pressure; + double windSpeed; + int windDeg; + int clouds; + double rain1h; + double rain3h; + double snow1h; + double snow3h; + std::string icons; + std::string from; +}; \ No newline at end of file -- GitLab