From 396aa8d80792f93f7a948fcbbab99d85e333b2ce Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Tue, 4 Oct 2022 01:24:15 +0200 Subject: [PATCH] Initial start on Recorder --- TODO.md | 8 +- recorder/include/recorder.h | 45 +++++++++ recorder/recorder.cpp | 180 +++++++++++++++++++++++++++++++++++ websocket/websocket.cpp | 2 +- xplugin/CMakeLists.txt | 3 + xplugin/include/main.h | 15 +-- xplugin/main.cpp | 181 +++--------------------------------- 7 files changed, 250 insertions(+), 184 deletions(-) create mode 100644 recorder/recorder.cpp diff --git a/TODO.md b/TODO.md index 7c66e55..8a87e69 100644 --- a/TODO.md +++ b/TODO.md @@ -15,4 +15,10 @@ - path: Path to ACF/AIR/Whatever on MSFS - hash: Hash of file at path - Requires mapping akin to C# - - Try to be fast \ No newline at end of file + - Try to be fast + - Define Protocoll + - Login Master Slave + - Commands + - Text + - Port + - Time \ No newline at end of file diff --git a/recorder/include/recorder.h b/recorder/include/recorder.h index 38fbdf8..c33fd0d 100644 --- a/recorder/include/recorder.h +++ b/recorder/include/recorder.h @@ -1,6 +1,19 @@ #ifndef GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H #define GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H +#include +#include +#include +#include +#include + +#include "websocket.h" + +#include "config/config.hpp" +#include "logbook/logbook.hpp" +#include "recording/recording.hpp" +#include "simdata/simDatabase.hpp" + namespace germanairlinesva { namespace gaconnector @@ -9,6 +22,38 @@ namespace gaconnector { class Recorder { + private: + std::function toLog; + + std::mutex mutex; + std::thread serverThread; + std::thread recordingThread; + std::atomic wantsExit{false}; + + std::shared_ptr configuration; + std::unique_ptr database; + std::unique_ptr connector; + + websocket::data toSend; + + std::queue> &messageQueue() + { + static std::queue> _messageQueue; + return _messageQueue; + } + + void serverWorker(); + void recordingWorker(); + + // For Testing + void test() const; + + public: + Recorder(int simVersion, std::function toLog); + ~Recorder(); + + void setData(websocket::data &data); + void handleMessages(); }; } // namespace recorder } // namespace gaconnector diff --git a/recorder/recorder.cpp b/recorder/recorder.cpp new file mode 100644 index 0000000..ed29e2f --- /dev/null +++ b/recorder/recorder.cpp @@ -0,0 +1,180 @@ +#include "include/recorder.h" + +namespace germanairlinesva +{ +namespace gaconnector +{ + namespace recorder + { + Recorder::Recorder(int simVersion, + std::function toLog) + : toLog(std::move(toLog)) + { + // Configuration + this->configuration = std::make_shared(); + this->toLog("Configuration loaded"); + +// Database +#ifdef XP + char hash[2 * MD5LEN + 1] = ""; + if (utilities::generateMD5(XPLANE_CUSTOM_SCENERY, hash, toLog) == 0) { + this->database = + std::make_unique(simVersion, + hash, + this->configuration, + this->toLog); + } +#endif +#ifndef MSFS +#endif + + // WebSocket + this->connector = std::make_unique( + "wss://ws.hofmannnet.myhome-server.de:8000", + this->configuration->getUser(), + this->toLog); + this->toLog("WebSocket started"); + + // For Testing + this->test(); + + // Thread for sending data to websocket + this->serverThread = std::thread(&Recorder::serverWorker, this); + this->recordingThread = std::thread(&Recorder::recordingWorker, this); + this->toLog("Workers started"); + } + + Recorder::~Recorder() + { + wantsExit = true; + serverThread.join(); + recordingThread.join(); + } + + void Recorder::setData(websocket::data &data) + { + const std::lock_guard lock(mutex); + + std::memcpy(&this->toSend, &data, sizeof(websocket::data)); + } + + void Recorder::handleMessages() + { + const std::lock_guard lock(mutex); + + if (!messageQueue().empty()) { + auto op = std::move(messageQueue().front()); + messageQueue().pop(); + op(); + } + } + + void Recorder::serverWorker() + { + utilities::setThreadName("GAServerWorker"); + + while (!wantsExit) { + struct websocket::data copy; + { + const std::lock_guard lock(mutex); + + std::memcpy(©, &toSend, sizeof(websocket::data)); + } + + connector->sendData(copy); + + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } + + toLog("Server thread stopped"); + } + + void Recorder::recordingWorker() + { + utilities::setThreadName("GARecordingWorker"); + + file::recording::Recording path; + file::recording::RecordingEntry lastPath; + std::uint32_t segment = 0; + + while (!wantsExit) { + struct websocket::data copy; + { + const std::lock_guard lock(mutex); + + std::memcpy(©, &toSend, sizeof(websocket::data)); + } + + file::recording::RecordingEntry currentPath( + segment, + static_cast(copy.alt), + static_cast(copy.gs), + {copy.lat, copy.lon}); + + if (strcmp(copy.path, "") != 0 && copy.pause && + lastPath != currentPath) { + path.addEntry(currentPath); + lastPath = currentPath; + } + + segment++; + + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + + path.toFile("flight.rec"); + toLog("Recording thread stopped"); + } + + void Recorder::test() const + { +#ifndef MSFS + this->toLog("Readback test of sim database using EDDF"); + auto ap = (*this->database)["EDDF"]; + for (const auto &it : ap.first) { + this->toLog(" " + it.to_string()); + } + for (const auto &it : ap.second) { + this->toLog(" " + it.to_string()); + } + this->toLog("Readback test of sim database using XXXX"); + auto ap2 = (*database)["XXXX"]; + ap2.first.size() == 0 ? this->toLog(" SUCCESS") : this->toLog(" ERROR"); +#endif + toLog("Logbook Test"); + germanairlinesva::file::logbook::Logbook logbook; + logbook.addEntry("08.09.2022", + "F", + "1000", + "L049", + "D-ALFA", + "John F. Kennedy International Aiport / EDDF", + "A1", + "14L", + "Gander International Airport / CYQX", + "10", + "03", + "10:00", + "10:20", + "13:20", + "13:30", + 210.5, + 20.1, + 5012.4156, + 8.87, + 5041.3856, + 7.1, + 971.14, + 2.41, + 980.65, + -165.23, + 1, + 1.2012, + "2022-09-08_VGA1000", + 5.5, + 1); + logbook.toFile(); + } + } // namespace recorder +} // namespace gaconnector +} // namespace germanairlinesva \ No newline at end of file diff --git a/websocket/websocket.cpp b/websocket/websocket.cpp index 6349fe9..3fdba98 100644 --- a/websocket/websocket.cpp +++ b/websocket/websocket.cpp @@ -91,7 +91,7 @@ namespace gaconnector if (strcmp(d.path, this->lastPath) != 0) { strcpy(this->lastPath, d.path); if (utilities::generateMD5(d.path, this->lastHash, this->toLog)) { - strcpy(this->lastHash, "NOT SET"); + strcpy(this->lastHash, "NO HASH"); } } diff --git a/xplugin/CMakeLists.txt b/xplugin/CMakeLists.txt index 5f193e5..74e0f26 100644 --- a/xplugin/CMakeLists.txt +++ b/xplugin/CMakeLists.txt @@ -1,12 +1,15 @@ file(GLOB socket CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/websocket/*.cpp) +file(GLOB recorder CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/recorder/*.cpp) add_library(germanairlinesva_xplugin SHARED ${socket} + ${recorder} main.cpp ) target_include_directories(germanairlinesva_xplugin PRIVATE ${CMAKE_SOURCE_DIR}/file/include + ${CMAKE_SOURCE_DIR}/recorder/include ${CMAKE_SOURCE_DIR}/simdata/include ${CMAKE_SOURCE_DIR}/websocket/include ${CMAKE_SOURCE_DIR}/utilities/include diff --git a/xplugin/include/main.h b/xplugin/include/main.h index b74960a..0c95828 100644 --- a/xplugin/include/main.h +++ b/xplugin/include/main.h @@ -1,24 +1,13 @@ #ifndef GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H #define GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H -#include + #include -#include #include #include -#include -#include #include #include -#include -#include "websocket.h" - -#include "config/config.hpp" -#include "constants.h" -#include "logbook/logbook.hpp" -#include "recording/recording.hpp" -#include "simdata/simDatabase.hpp" -#include "util.hpp" +#include "recorder.h" #include "XPLM/XPLMDataAccess.h" #include "XPLM/XPLMGraphics.h" diff --git a/xplugin/main.cpp b/xplugin/main.cpp index 1ac1a9d..49698ab 100644 --- a/xplugin/main.cpp +++ b/xplugin/main.cpp @@ -1,20 +1,5 @@ #include "include/main.h" -std::mutex mutex; -std::queue> &messageQueue() -{ - static std::queue> _messageQueue; - return _messageQueue; -} -std::thread serverThread; -std::thread recordingThread; -std::atomic wantsExit; - -std::shared_ptr configuration; -std::unique_ptr database; -std::unique_ptr connector; -int xplaneVersion; - /* Datarefs */ XPLMDataRef pauseIndicator; XPLMDataRef parkingBrake; @@ -44,21 +29,20 @@ XPLMDataRef roll; XPLMDataRef quaternion; struct germanairlinesva::gaconnector::websocket::data toSend; -germanairlinesva::file::recording::Recording p; +germanairlinesva::gaconnector::recorder::Recorder *recorder; /* * Callbacks */ - PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc) { + int xplaneVersion; + XPLMEnableFeature("XPLM_USE_NATIVE_PATHS", 1); XPLMGetVersions(&xplaneVersion, NULL, NULL); toLog("Plugin using X-Plane Version " + std::to_string(xplaneVersion)); - wantsExit.store(false); - /* First we must fill in the passed-in buffers to describe our * plugin to the plugin-system. */ @@ -111,77 +95,10 @@ PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc) roll = XPLMFindDataRef("sim/flightmodel/position/phi"); // FLOAT quaternion = XPLMFindDataRef("sim/flightmodel/position/q"); // FLOAT[4] - configuration = std::make_unique(); - toLog("Config loaded"); - - connector = - std::make_unique( - "wss://ws.hofmannnet.myhome-server.de:8000", - configuration->getUser(), - toLog); - toLog("WebSocket started"); - - char hash[2 * MD5LEN + 1] = ""; - if (germanairlinesva::utilities::generateMD5(XPLANE_CUSTOM_SCENERY, - hash, - toLog) == 0) { - database = std::make_unique( - xplaneVersion, - hash, - configuration, - toLog); - } - - toLog("Readback test of sim database using EDDF"); - auto ap = (*database)["EDDF"]; - for (const auto &it : ap.first) { - toLog(" " + it.to_string()); - } - for (const auto &it : ap.second) { - toLog(" " + it.to_string()); - } - toLog("Readback test of sim database using XXXX"); - auto ap2 = (*database)["XXXX"]; - ap2.first.size() == 0 ? toLog(" SUCCESS") : toLog(" ERROR"); - - // Thread for sending data to websocket - serverThread = std::thread(&serverWorker); - recordingThread = std::thread(&recordingWorker); - toLog("Workers started"); - - toLog("Logbook Test"); - germanairlinesva::file::logbook::Logbook logbook; - logbook.addEntry("08.09.2022", - "F", - "1000", - "L049", - "D-ALFA", - "John F. Kennedy International Aiport / EDDF", - "A1", - "14L", - "Gander International Airport / CYQX", - "10", - "03", - "10:00", - "10:20", - "13:20", - "13:30", - 210.5, - 20.1, - 5012.4156, - 8.87, - 5041.3856, - 7.1, - 971.14, - 2.41, - 980.65, - -165.23, - 1, - 1.2012, - "2022-09-08_VGA1000", - 5.5, - 1); - logbook.toFile(); + // Recorder + recorder = + new germanairlinesva::gaconnector::recorder::Recorder(xplaneVersion, + toLog); return 1; } @@ -190,12 +107,9 @@ PLUGIN_API void XPluginStop(void) { /* Flight Loop */ XPLMUnregisterFlightLoopCallback(flightLoop, nullptr); - /* End threads */ - wantsExit = true; - serverThread.join(); - recordingThread.join(); - p.toFile("flight.rec"); + /* End threads */ + recorder->~Recorder(); toLog("Plugin stopped"); } @@ -216,8 +130,6 @@ PLUGIN_API void #pragma clang diagnostic ignored "-Wunused-parameter" float flightLoop(float elapsedMe, float elapsedSim, int counter, void *refcon) { - const std::lock_guard lock(mutex); - std::memset(&toSend, 0, sizeof(germanairlinesva::gaconnector::websocket::data)); @@ -246,83 +158,14 @@ float flightLoop(float elapsedMe, float elapsedSim, int counter, void *refcon) toSend.payloadKg = XPLMGetDataf(payloadKgs); toSend.totalWeightKg = XPLMGetDataf(totalWeightKgs); - if (!messageQueue().empty()) { - auto op = std::move(messageQueue().front()); - messageQueue().pop(); - op(); - } + recorder->setData(toSend); + + recorder->handleMessages(); return -1; } #pragma clang diagnostic pop -void serverWorker() -{ - germanairlinesva::utilities::setThreadName("GAServerWorker"); - - while (!wantsExit) { - struct germanairlinesva::gaconnector::websocket::data copy; - { - const std::lock_guard lock(mutex); - - std::memcpy(©, - &toSend, - sizeof(germanairlinesva::gaconnector::websocket::data)); - } - - connector->sendData(copy); - - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - - toLog("Server thread stopped"); -} - -void recordingWorker() -{ - germanairlinesva::utilities::setThreadName("GARecordingWorker"); - - germanairlinesva::file::recording::RecordingEntry lastPath; - std::uint32_t segment = 0; - - auto ap = (*database)["EDDF"]; - auto rwys = ap.second; - - while (!wantsExit) { - struct germanairlinesva::gaconnector::websocket::data copy; - { - const std::lock_guard lock(mutex); - - std::memcpy(©, - &toSend, - sizeof(germanairlinesva::gaconnector::websocket::data)); - } - - germanairlinesva::file::recording::RecordingEntry currentPath( - segment, - static_cast(copy.alt), - static_cast(copy.gs), - {copy.lat, copy.lon}); - - if (strcmp(copy.path, "") != 0 && copy.pause && lastPath != currentPath) { - p.addEntry(currentPath); - lastPath = currentPath; - - for (const auto &it : rwys) { - if (it.containsPoint({copy.lat, copy.lon})) { - toLog("On Runway: " + it.to_string()); - } - } - } - - segment++; - - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - } - - toLog("Recording thread stopped"); -} - void toLog(const std::string &message) { std::time_t utc = std::time(nullptr);