Compare commits

..

No commits in common. "396aa8d80792f93f7a948fcbbab99d85e333b2ce" and "42acea35bb18d9f03da8be0c5b4dba8ab1f2889e" have entirely different histories.

25 changed files with 607 additions and 733 deletions

View File

@ -16,9 +16,3 @@
- hash: Hash of file at path - hash: Hash of file at path
- Requires mapping akin to C# - Requires mapping akin to C#
- Try to be fast - Try to be fast
- Define Protocoll
- Login Master Slave
- Commands
- Text
- Port
- Time

View File

@ -100,7 +100,7 @@ class SimConnect
bool pausedMenu; bool pausedMenu;
bool paused; bool paused;
std::mutex mutex; std::mutex mutex;
struct germanairlinesva::gaconnector::websocket::data simData; struct germanairlinesva::websocket::data simData;
std::shared_ptr<germanairlinesva::file::config::Config> configuration; std::shared_ptr<germanairlinesva::file::config::Config> configuration;
std::function<void(const std::string)> toLog; std::function<void(const std::string)> toLog;
@ -117,7 +117,7 @@ class SimConnect
~SimConnect(); ~SimConnect();
bool isConnected() const; bool isConnected() const;
const std::string getVersion() const; const std::string getVersion() const;
void getData(struct germanairlinesva::gaconnector::websocket::data *data); void getData(struct germanairlinesva::websocket::data *data);
void getStates() const; void getStates() const;
void handleMessage(); void handleMessage();
}; };

View File

@ -16,11 +16,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <windows.h> #include <windows.h>
#include "_simconnect.h"
#include "config/config.hpp" #include "config/config.hpp"
#include "constants.h" #include "constants.h"
#include "logbook/logbook.hpp" #include "logbook/logbook.hpp"
#include "recording/recording.hpp" #include "recording/recording.hpp"
#include "_simconnect.h"
#include "simdata/simDatabase.hpp" #include "simdata/simDatabase.hpp"
WINBOOL addNotifyIcon(HWND hWnd); WINBOOL addNotifyIcon(HWND hWnd);

View File

@ -12,10 +12,10 @@ std::atomic<bool> wantsExit;
std::shared_ptr<germanairlinesva::file::config::Config> configuration; std::shared_ptr<germanairlinesva::file::config::Config> configuration;
std::unique_ptr<germanairlinesva::file::simdata::SimDatabase> database; std::unique_ptr<germanairlinesva::file::simdata::SimDatabase> database;
std::unique_ptr<germanairlinesva::gaconnector::websocket::Websocket> connector; std::unique_ptr<germanairlinesva::websocket::Websocket> connector;
std::unique_ptr<SimConnect> simConnect; std::unique_ptr<SimConnect> simConnect;
struct germanairlinesva::gaconnector::websocket::data toSend; struct germanairlinesva::websocket::data toSend;
germanairlinesva::file::recording::Recording p; germanairlinesva::file::recording::Recording p;
// The Window Procedure // The Window Procedure
@ -127,8 +127,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
configuration = std::make_unique<germanairlinesva::file::config::Config>(); configuration = std::make_unique<germanairlinesva::file::config::Config>();
toLog("Config loaded"); toLog("Config loaded");
connector = connector = std::make_unique<germanairlinesva::websocket::Websocket>(
std::make_unique<germanairlinesva::gaconnector::websocket::Websocket>(
"wss://ws.hofmannnet.myhome-server.de:8000", "wss://ws.hofmannnet.myhome-server.de:8000",
configuration->getUser(), configuration->getUser(),
toLog); toLog);
@ -154,8 +153,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
CoTaskMemFree(folder); CoTaskMemFree(folder);
char hash[2 * MD5LEN + 1] = ""; char hash[2 * MD5LEN + 1] = "";
if (germanairlinesva::utilities::generateMD5(path.c_str(), hash, toLog) == if (germanairlinesva::util::generateMD5(path.c_str(), hash, toLog) == 0) {
0) {
database = std::make_unique<germanairlinesva::file::simdata::SimDatabase>( database = std::make_unique<germanairlinesva::file::simdata::SimDatabase>(
FSX_VERSION, FSX_VERSION,
hash, hash,
@ -326,13 +324,13 @@ void end(HWND hWnd)
void serverWorker() void serverWorker()
{ {
germanairlinesva::utilities::setThreadName("GAServerWorker"); germanairlinesva::util::setThreadName("GAServerWorker");
while (!wantsExit) { while (!wantsExit) {
simConnect->getStates(); simConnect->getStates();
struct germanairlinesva::gaconnector::websocket::data *copy = struct germanairlinesva::websocket::data *copy =
new germanairlinesva::gaconnector::websocket::data(); new germanairlinesva::websocket::data();
{ {
const std::lock_guard<std::mutex> lock(mutex); const std::lock_guard<std::mutex> lock(mutex);
@ -349,7 +347,7 @@ void serverWorker()
void recordingWorker() void recordingWorker()
{ {
germanairlinesva::utilities::setThreadName("GARecordingWorker"); germanairlinesva::util::setThreadName("GARecordingWorker");
germanairlinesva::file::recording::RecordingEntry lastPath; germanairlinesva::file::recording::RecordingEntry lastPath;
std::uint32_t segment = 0; std::uint32_t segment = 0;
@ -358,8 +356,8 @@ void recordingWorker()
auto rwys = ap.second; auto rwys = ap.second;
while (!wantsExit) { while (!wantsExit) {
struct germanairlinesva::gaconnector::websocket::data *copy = struct germanairlinesva::websocket::data *copy =
new germanairlinesva::gaconnector::websocket::data(); new germanairlinesva::websocket::data();
{ {
const std::lock_guard<std::mutex> lock(mutex); const std::lock_guard<std::mutex> lock(mutex);

View File

@ -323,8 +323,7 @@ const std::string SimConnect::getVersion() const
} }
} }
void SimConnect::getData( void SimConnect::getData(struct germanairlinesva::websocket::data *data)
struct germanairlinesva::gaconnector::websocket::data *data)
{ {
const std::lock_guard<std::mutex> lock(this->mutex); const std::lock_guard<std::mutex> lock(this->mutex);
memcpy(data, &this->simData, sizeof(this->simData)); memcpy(data, &this->simData, sizeof(this->simData));

View File

@ -51,10 +51,10 @@ namespace file
std::ifstream in(BASE_DIRECTORY CONFIG); std::ifstream in(BASE_DIRECTORY CONFIG);
std::string line; std::string line;
while (std::getline(in, line)) { while (std::getline(in, line)) {
std::vector<std::string> fields = utilities::split(line, '='); std::vector<std::string> fields = util::split(line, '=');
if (fields.size() >= 2) { if (fields.size() >= 2) {
utilities::trim(fields[0]); util::trim(fields[0]);
utilities::trim(fields[1]); util::trim(fields[1]);
if (fields[0] == "scenery") { if (fields[0] == "scenery") {
this->scenery = fields[1]; this->scenery = fields[1];
} else if (fields[0] == "user") { } else if (fields[0] == "user") {

View File

@ -117,7 +117,7 @@ namespace file
public: public:
inline Logbook() inline Logbook()
{ {
if (utilities::fileExists(BASE_DIRECTORY LOGBOOK)) { if (util::fileExists(BASE_DIRECTORY LOGBOOK)) {
this->fromFile(); this->fromFile();
} }
} }

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_FILE_RECORDING_RECORDINGENTRY_H #ifndef GERMANAIRLINESVA_FILE_RECORDINGENTRY_H
#define GERMANAIRLINESVA_FILE_RECORDING_RECORDINGENTRY_H #define GERMANAIRLINESVA_FILE_RECORDINGENTRY_H
#include <cstdint> #include <cstdint>
#include <fstream> #include <fstream>
@ -26,14 +26,14 @@ namespace file
std::uint32_t time; std::uint32_t time;
std::uint16_t altitude = 0; std::uint16_t altitude = 0;
std::uint16_t groundSpeed = 0; std::uint16_t groundSpeed = 0;
struct utilities::geodata::point coordinates = {NAN, NAN}; struct geodata::point coordinates = {NAN, NAN};
public: public:
inline RecordingEntry() = default; inline RecordingEntry() = default;
inline RecordingEntry(std::uint32_t time, inline RecordingEntry(std::uint32_t time,
std::uint16_t altitude, std::uint16_t altitude,
std::uint16_t groundSpeed, std::uint16_t groundSpeed,
struct utilities::geodata::point coordinates) struct geodata::point coordinates)
: time(time), altitude(altitude), groundSpeed(groundSpeed), : time(time), altitude(altitude), groundSpeed(groundSpeed),
coordinates(coordinates) coordinates(coordinates)
{ {

View File

@ -32,7 +32,7 @@ namespace file
{ {
private: private:
std::string designator; std::string designator;
struct utilities::geodata::point center; struct geodata::point center;
std::uint8_t radius; std::uint8_t radius;
public: public:
@ -45,7 +45,7 @@ namespace file
radius(radius){}; radius(radius){};
// From Database // From Database
inline Gate(std::string designator, inline Gate(std::string designator,
struct utilities::geodata::point center, struct geodata::point center,
std::uint8_t radius) std::uint8_t radius)
: designator(designator), center(center), radius(radius){}; : designator(designator), center(center), radius(radius){};
@ -56,9 +56,9 @@ namespace file
write<decltype(this->radius)>(out, this->radius); write<decltype(this->radius)>(out, this->radius);
} }
inline bool contains(utilities::geodata::point coordinates) const inline bool contains(geodata::point coordinates) const
{ {
return utilities::geodata::distanceEarthP(this->center, coordinates); return geodata::distanceEarthP(this->center, coordinates);
} }
inline const std::string to_string() const inline const std::string to_string() const

View File

@ -34,7 +34,7 @@ namespace file
{ {
private: private:
std::string designator; std::string designator;
struct utilities::geodata::box bounds; struct geodata::box bounds;
std::uint8_t width; std::uint8_t width;
std::uint16_t length; std::uint16_t length;
double trueHeading; double trueHeading;
@ -49,51 +49,49 @@ namespace file
double width) double width)
: designator(designator), width(width) : designator(designator), width(width)
{ {
this->length = utilities::geodata::distanceEarthD(latitudeStart, this->length = geodata::distanceEarthD(latitudeStart,
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd); longitudeEnd);
this->trueHeading = utilities::geodata::bearingDD(latitudeStart, this->trueHeading = geodata::bearingDD(latitudeStart,
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd); longitudeEnd);
this->bounds = utilities::geodata::calculateBoxDD( this->bounds =
{latitudeStart, longitudeStart}, geodata::calculateBoxDD({latitudeStart, longitudeStart},
{latitudeEnd, longitudeEnd}, {latitudeEnd, longitudeEnd},
this->trueHeading, this->trueHeading,
this->width); this->width);
}; };
// From MakeRwys // From MakeRwys
inline Runway(std::string designator, inline Runway(std::string designator,
struct utilities::geodata::point start, struct geodata::point start,
double width, double width,
double length, double length,
double trueHeading) double trueHeading)
: designator(designator), width(width), length(length), : designator(designator), width(width), length(length),
trueHeading(trueHeading) trueHeading(trueHeading)
{ {
utilities::geodata::point end = geodata::point end =
utilities::geodata::calculatePointDD(start, trueHeading, length); geodata::calculatePointDD(start, trueHeading, length);
this->bounds = utilities::geodata::calculateBoxDD(start, this->bounds =
end, geodata::calculateBoxDD(start, end, trueHeading, width);
trueHeading,
width);
}; };
// From database // From database
inline Runway(std::string designator, inline Runway(std::string designator,
struct utilities::geodata::box bounds, struct geodata::box bounds,
std::uint8_t width, std::uint8_t width,
std::uint16_t length, std::uint16_t length,
double trueHeading) double trueHeading)
: designator(designator), bounds(bounds), width(width), : designator(designator), bounds(bounds), width(width),
length(length), trueHeading(trueHeading){}; length(length), trueHeading(trueHeading){};
inline bool containsPoint(const utilities::geodata::point point) const inline bool containsPoint(const geodata::point point) const
{ {
size_t j = 3; size_t j = 3;
bool c = false; bool c = false;
std::vector<utilities::geodata::point> poly{this->bounds.topLeft, std::vector<geodata::point> poly{this->bounds.topLeft,
this->bounds.topRight, this->bounds.topRight,
this->bounds.bottomRight, this->bounds.bottomRight,
this->bounds.bottomLeft}; this->bounds.bottomLeft};

View File

@ -19,7 +19,7 @@
#ifdef XP #ifdef XP
#include "simdata/simdataXP.hpp" #include "simdata/simdataXP.hpp"
#endif #endif
#if not defined(XP) && not defined(MSFS) #ifndef MSFS
#include "simdata/simdataESP.hpp" #include "simdata/simdataESP.hpp"
#endif #endif
@ -61,8 +61,7 @@ namespace file
std::uint16_t numGates = read<std::uint16_t>(in); std::uint16_t numGates = read<std::uint16_t>(in);
for (int j = 0; j < numGates; j++) { for (int j = 0; j < numGates; j++) {
std::string designator = readString(in); std::string designator = readString(in);
struct utilities::geodata::point center = struct geodata::point center = read<struct geodata::point>(in);
read<struct utilities::geodata::point>(in);
std::uint8_t radius = read<std::uint8_t>(in); std::uint8_t radius = read<std::uint8_t>(in);
this->airports[icao].first.emplace_back(designator, this->airports[icao].first.emplace_back(designator,
@ -74,8 +73,7 @@ namespace file
for (int j = 0; j < numRunways; j++) { for (int j = 0; j < numRunways; j++) {
std::string designator = readString(in); std::string designator = readString(in);
// Center // Center
struct utilities::geodata::box bounds = struct geodata::box bounds = read<struct geodata::box>(in);
read<struct utilities::geodata::box>(in);
std::uint8_t width = read<std::uint8_t>(in); std::uint8_t width = read<std::uint8_t>(in);
std::uint16_t length = read<std::uint16_t>(in); std::uint16_t length = read<std::uint16_t>(in);
double trueHeading = read<double>(in); double trueHeading = read<double>(in);
@ -115,7 +113,7 @@ namespace file
std::function<void(const std::string)> toLog) std::function<void(const std::string)> toLog)
{ {
if (strcmp(configuration->getScenery().c_str(), hash) != 0 || if (strcmp(configuration->getScenery().c_str(), hash) != 0 ||
!utilities::fileExists(BASE_DIRECTORY SIMDATABASE)) { !util::fileExists(BASE_DIRECTORY SIMDATABASE)) {
#ifdef XP #ifdef XP
scan(simVersion < 12000 ? XPLANE11_BASE_SCENERY scan(simVersion < 12000 ? XPLANE11_BASE_SCENERY
: XPLANE12_BASE_SCENERY, : XPLANE12_BASE_SCENERY,

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAESP_H #ifndef GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAXP_H
#define GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAESP_H #define GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAXP_H
#include <cstdint> #include <cstdint>
#include <fstream> #include <fstream>
@ -55,7 +55,7 @@ namespace file
log << "<FILE> " << runwaysFile << std::endl; log << "<FILE> " << runwaysFile << std::endl;
while (std::getline(runways, line)) { while (std::getline(runways, line)) {
std::vector<std::string> fields = utilities::split(line, ','); std::vector<std::string> fields = util::split(line, ',');
// New ICAO // New ICAO
if (currentIcao != nullptr && *currentIcao != fields[0]) { if (currentIcao != nullptr && *currentIcao != fields[0]) {
tmpAirportRunways[*currentIcao] = tmpRunways; tmpAirportRunways[*currentIcao] = tmpRunways;
@ -85,13 +85,12 @@ namespace file
designator = "0" + designator; designator = "0" + designator;
} }
struct utilities::geodata::point start = {std::stod(fields[2]), struct geodata::point start = {std::stod(fields[2]),
std::stod(fields[3])}; std::stod(fields[3])};
tmpRunways.emplace_back( tmpRunways.emplace_back(designator,
designator,
start, start,
utilities::geodata::toMetre(std::stod(fields[8])), geodata::toMetre(std::stod(fields[8])),
utilities::geodata::toMetre(std::stod(fields[6])), geodata::toMetre(std::stod(fields[6])),
std::stod(fields[5]) + std::stod(fields[9])); std::stod(fields[5]) + std::stod(fields[9]));
log << "\t<RUNWAY> " << line << std::endl; log << "\t<RUNWAY> " << line << std::endl;
@ -99,7 +98,7 @@ namespace file
currentIcao = nullptr; currentIcao = nullptr;
while (std::getline(gates, line)) { while (std::getline(gates, line)) {
std::vector<std::string> fields = utilities::split(line, ','); std::vector<std::string> fields = util::split(line, ',');
// New ICAO // New ICAO
if (currentIcao != nullptr && *currentIcao != fields[0]) { if (currentIcao != nullptr && *currentIcao != fields[0]) {
tmpAirportGates[*currentIcao] = tmpGates; tmpAirportGates[*currentIcao] = tmpGates;

View File

@ -79,9 +79,8 @@ namespace file
int validCount = 0; int validCount = 0;
while (std::getline(infile, line)) { while (std::getline(infile, line)) {
std::vector<std::string> fields = utilities::split(line, ' '); std::vector<std::string> fields = util::split(line, ' ');
fields = fields = util::select_T<std::string>(fields, [](const std::string &s) {
utilities::select_T<std::string>(fields, [](const std::string &s) {
return s.length() > 0; return s.length() > 0;
}); });
@ -174,7 +173,7 @@ namespace file
std::vector<std::string> packs; std::vector<std::string> packs;
while (std::getline(custom, line)) { while (std::getline(custom, line)) {
if ((pos = line.find("SCENERY_PACK")) != std::string::npos) { if ((pos = line.find("SCENERY_PACK")) != std::string::npos) {
std::string path = utilities::rtrim_copy(line.substr(pos + 13)) + std::string path = util::rtrim_copy(line.substr(pos + 13)) +
"Earth nav data/apt.dat"; "Earth nav data/apt.dat";
packs.emplace_back(path); packs.emplace_back(path);
} }

View File

@ -2,7 +2,7 @@
shopt -s globstar shopt -s globstar
GLOBIGNORE='**/XPLM/**:XPLM/**:**/XPLM:**/ixwebsocket/**:ixwebsocket/**:**/ixwebsocket:**/nlohmann/**:nlohmann/**:**/nlohmann:**/XPSDK/**:XPSDK/**:**/XPSDK:**/build*/**:build*/**:**/build*:**/openSSL/**:openSSL/**:**/openSSL:**/SimConnect/**:SimConnect/**:**/SimConnect' GLOBIGNORE='**/XPLM/**:XPLM/**:**/XPLM:**/ixwebsocket/**:ixwebsocket/**:**/ixwebsocket:**/nlohmann/**:nlohmann/**:**/nlohmann:**/XPSDK/**:XPSDK/**:**/XPSDK:**/build*/**:build*/**:**/build*:**/openSSL/**:openSSL/**:**/openSSL'
clang-format -verbose -i **/*.cpp clang-format -verbose -i **/*.cpp
clang-format -verbose -i **/*.h clang-format -verbose -i **/*.h

View File

@ -1,62 +0,0 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H
#define GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H
#include <atomic>
#include <functional>
#include <mutex>
#include <queue>
#include <thread>
#include "websocket.h"
#include "config/config.hpp"
#include "logbook/logbook.hpp"
#include "recording/recording.hpp"
#include "simdata/simDatabase.hpp"
namespace germanairlinesva
{
namespace gaconnector
{
namespace recorder
{
class Recorder
{
private:
std::function<void(const std::string)> toLog;
std::mutex mutex;
std::thread serverThread;
std::thread recordingThread;
std::atomic<bool> wantsExit{false};
std::shared_ptr<file::config::Config> configuration;
std::unique_ptr<file::simdata::SimDatabase> database;
std::unique_ptr<websocket::Websocket> connector;
websocket::data toSend;
std::queue<std::function<void()>> &messageQueue()
{
static std::queue<std::function<void()>> _messageQueue;
return _messageQueue;
}
void serverWorker();
void recordingWorker();
// For Testing
void test() const;
public:
Recorder(int simVersion, std::function<void(const std::string)> toLog);
~Recorder();
void setData(websocket::data &data);
void handleMessages();
};
} // namespace recorder
} // namespace gaconnector
} // namespace germanairlinesva
#endif

View File

@ -1,180 +0,0 @@
#include "include/recorder.h"
namespace germanairlinesva
{
namespace gaconnector
{
namespace recorder
{
Recorder::Recorder(int simVersion,
std::function<void(const std::string)> toLog)
: toLog(std::move(toLog))
{
// Configuration
this->configuration = std::make_shared<file::config::Config>();
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<file::simdata::SimDatabase>(simVersion,
hash,
this->configuration,
this->toLog);
}
#endif
#ifndef MSFS
#endif
// WebSocket
this->connector = std::make_unique<websocket::Websocket>(
"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<std::mutex> lock(mutex);
std::memcpy(&this->toSend, &data, sizeof(websocket::data));
}
void Recorder::handleMessages()
{
const std::lock_guard<std::mutex> 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<std::mutex> lock(mutex);
std::memcpy(&copy, &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<std::mutex> lock(mutex);
std::memcpy(&copy, &toSend, sizeof(websocket::data));
}
file::recording::RecordingEntry currentPath(
segment,
static_cast<std::uint16_t>(copy.alt),
static_cast<std::uint16_t>(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

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_UTILITIES_CONSTANTS_H #ifndef GERMANAIRLINESVA_GACONNECTOR_CONSTANTS_H
#define GERMANAIRLINESVA_UTILITIES_CONSTANTS_H #define GERMANAIRLINESVA_GACONNECTOR_CONSTANTS_H
#ifdef XP #ifdef XP
#define BASE_DIRECTORY "Resources/plugins/GAConnector/" #define BASE_DIRECTORY "Resources/plugins/GAConnector/"

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_UTILITIES_GEODATA_H #ifndef GERMANAIRLINESVA_GACONNECTOR_GEODATA_H
#define GERMANAIRLINESVA_UTILITIES_GEODATA_H #define GERMANAIRLINESVA_GACONNECTOR_GEODATA_H
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#define BUFSIZE 1024 #define BUFSIZE 1024
@ -10,10 +10,8 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace utilities namespace geodata
{ {
namespace geodata
{
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct point { struct point {
@ -93,8 +91,7 @@ namespace utilities
lon2r = toRadians(toLongitude); lon2r = toRadians(toLongitude);
u = sin((lat2r - lat1r) / 2); u = sin((lat2r - lat1r) / 2);
v = sin((lon2r - lon1r) / 2); v = sin((lon2r - lon1r) / 2);
return 2.0 * EARTH_M * return 2.0 * EARTH_M * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
} }
// Input in degrees, Output in metres // Input in degrees, Output in metres
@ -107,8 +104,7 @@ namespace utilities
lon2r = toRadians(to.longitude); lon2r = toRadians(to.longitude);
u = sin((lat2r - lat1r) / 2); u = sin((lat2r - lat1r) / 2);
v = sin((lon2r - lon1r) / 2); v = sin((lon2r - lon1r) / 2);
return 2.0 * EARTH_M * return 2.0 * EARTH_M * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
} }
// Input and Output in degrees // Input and Output in degrees
@ -173,8 +169,7 @@ namespace utilities
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) * std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
std::cos(coordinates.latitude), std::cos(coordinates.latitude),
std::cos(distance / EARTH_M) - std::cos(distance / EARTH_M) -
std::sin(coordinates.latitude) * std::sin(coordinates.latitude) * std::sin(newLatitude));
std::sin(newLatitude));
return {toDegrees(newLatitude), toDegrees(newLongitude)}; return {toDegrees(newLatitude), toDegrees(newLongitude)};
} }
@ -195,8 +190,7 @@ namespace utilities
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) * std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
std::cos(coordinates.latitude), std::cos(coordinates.latitude),
std::cos(distance / EARTH_M) - std::cos(distance / EARTH_M) -
std::sin(coordinates.latitude) * std::sin(coordinates.latitude) * std::sin(newLatitude));
std::sin(newLatitude));
return {newLatitude, newLongitude}; return {newLatitude, newLongitude};
} }
@ -207,8 +201,7 @@ namespace utilities
double length, double length,
double width) double width)
{ {
struct point primaryCenter = struct point primaryCenter = calculatePointDR(center, bearing, -length / 2);
calculatePointDR(center, bearing, -length / 2);
struct point secondaryCenter = struct point secondaryCenter =
calculatePointDR(center, bearing, length / 2); calculatePointDR(center, bearing, length / 2);
double offsetHeadingNorth = double offsetHeadingNorth =
@ -244,8 +237,8 @@ namespace utilities
return {primaryTop, secondaryTop, secondaryBottom, primaryBottom}; return {primaryTop, secondaryTop, secondaryBottom, primaryBottom};
} }
} // namespace geodata
} // namespace utilities } // namespace geodata
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_UTILITIES_UTIL_H #ifndef GERMANAIRLINESVA_GACONNECTOR_UTIL_H
#define GERMANAIRLINESVA_UTILITIES_UTIL_H #define GERMANAIRLINESVA_GACONNECTOR_UTIL_H
#define BUFSIZE 1024 #define BUFSIZE 1024
#define MD5LEN 16 #define MD5LEN 16
@ -36,7 +36,7 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace utilities namespace util
{ {
template <typename T> template <typename T>
static inline std::vector<T> static inline std::vector<T>
@ -294,7 +294,7 @@ namespace utilities
return result; return result;
} }
} // namespace utilities } // namespace util
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif

View File

@ -1,14 +1,12 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_TYPES_H #ifndef GERMANAIRLINESVA_GACONNECTOR_SOCKET_TYPES_H
#define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_TYPES_H #define GERMANAIRLINESVA_GACONNECTOR_SOCKET_TYPES_H
#include <cstdint> #include <cstdint>
namespace germanairlinesva namespace germanairlinesva
{ {
namespace gaconnector namespace websocket
{ {
namespace websocket
{
#pragma pack(push) /* push current alignment to stack */ #pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */ #pragma pack(1) /* set alignment to 1 byte boundary */
@ -34,17 +32,7 @@ namespace gaconnector
float totalWeightKg = 0; float totalWeightKg = 0;
}; };
enum commands { enum commands { PROCESS, SAVE, LOAD, TEXT, TIME, UNPAUSE, PAUSE, PORT, END };
PROCESS,
SAVE,
LOAD,
TEXT,
TIME,
UNPAUSE,
PAUSE,
PORT,
END
};
struct command_base { struct command_base {
enum commands type; enum commands type;
@ -57,8 +45,7 @@ namespace gaconnector
}; };
#pragma pack(pop) /* restore original alignment from stack */ #pragma pack(pop) /* restore original alignment from stack */
} // namespace websocket } // namespace websocket
} // namespace gaconnector
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif

View File

@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_WEBSOCKET_H #ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_H
#define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_WEBSOCKET_H #define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_H
#define BUFSIZE 1024 #define BUFSIZE 1024
#define MD5LEN 16 #define MD5LEN 16
@ -20,10 +20,8 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace gaconnector namespace websocket
{ {
namespace websocket
{
class Websocket class Websocket
{ {
private: private:
@ -42,8 +40,7 @@ namespace gaconnector
void onClientMessageCallback(const ix::WebSocketMessagePtr &msg); void onClientMessageCallback(const ix::WebSocketMessagePtr &msg);
void sendData(data &d); void sendData(data &d);
}; };
} // namespace websocket } // namespace websocket
} // namespace gaconnector
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif

View File

@ -2,10 +2,8 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace gaconnector namespace websocket
{ {
namespace websocket
{
Websocket::Websocket(std::string host, Websocket::Websocket(std::string host,
std::string user, std::string user,
std::function<void(const std::string)> toLog) std::function<void(const std::string)> toLog)
@ -90,8 +88,8 @@ namespace gaconnector
{ {
if (strcmp(d.path, this->lastPath) != 0) { if (strcmp(d.path, this->lastPath) != 0) {
strcpy(this->lastPath, d.path); strcpy(this->lastPath, d.path);
if (utilities::generateMD5(d.path, this->lastHash, this->toLog)) { if (util::generateMD5(d.path, this->lastHash, this->toLog)) {
strcpy(this->lastHash, "NO HASH"); strcpy(this->lastHash, "NOT SET");
} }
} }
@ -112,6 +110,5 @@ namespace gaconnector
this->webSocket->send(msg.str(), false); this->webSocket->send(msg.str(), false);
} }
} }
} // namespace websocket } // namespace websocket
} // namespace gaconnector
} // namespace germanairlinesva } // namespace germanairlinesva

View File

@ -1,15 +1,12 @@
file(GLOB socket CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/websocket/*.cpp) 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 add_library(germanairlinesva_xplugin SHARED
${socket} ${socket}
${recorder}
main.cpp main.cpp
) )
target_include_directories(germanairlinesva_xplugin PRIVATE target_include_directories(germanairlinesva_xplugin PRIVATE
${CMAKE_SOURCE_DIR}/file/include ${CMAKE_SOURCE_DIR}/file/include
${CMAKE_SOURCE_DIR}/recorder/include
${CMAKE_SOURCE_DIR}/simdata/include ${CMAKE_SOURCE_DIR}/simdata/include
${CMAKE_SOURCE_DIR}/websocket/include ${CMAKE_SOURCE_DIR}/websocket/include
${CMAKE_SOURCE_DIR}/utilities/include ${CMAKE_SOURCE_DIR}/utilities/include

View File

@ -1,13 +1,24 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H #ifndef GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H
#define GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H #define GERMANAIRLINESVA_GACONNECTOR_XPLUGIN_MAIN_H
#include <atomic>
#include <chrono> #include <chrono>
#include <cstdint>
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <mutex>
#include <queue>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <thread>
#include "recorder.h" #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 "XPLM/XPLMDataAccess.h" #include "XPLM/XPLMDataAccess.h"
#include "XPLM/XPLMGraphics.h" #include "XPLM/XPLMGraphics.h"

View File

@ -1,5 +1,20 @@
#include "include/main.h" #include "include/main.h"
std::mutex mutex;
std::queue<std::function<void()>> &messageQueue()
{
static std::queue<std::function<void()>> _messageQueue;
return _messageQueue;
}
std::thread serverThread;
std::thread recordingThread;
std::atomic<bool> wantsExit;
std::shared_ptr<germanairlinesva::file::config::Config> configuration;
std::unique_ptr<germanairlinesva::file::simdata::SimDatabase> database;
std::unique_ptr<germanairlinesva::websocket::Websocket> connector;
int xplaneVersion;
/* Datarefs */ /* Datarefs */
XPLMDataRef pauseIndicator; XPLMDataRef pauseIndicator;
XPLMDataRef parkingBrake; XPLMDataRef parkingBrake;
@ -28,21 +43,22 @@ XPLMDataRef pitch;
XPLMDataRef roll; XPLMDataRef roll;
XPLMDataRef quaternion; XPLMDataRef quaternion;
struct germanairlinesva::gaconnector::websocket::data toSend; struct germanairlinesva::websocket::data toSend;
germanairlinesva::gaconnector::recorder::Recorder *recorder; germanairlinesva::file::recording::Recording p;
/* /*
* Callbacks * Callbacks
*/ */
PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc) PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc)
{ {
int xplaneVersion;
XPLMEnableFeature("XPLM_USE_NATIVE_PATHS", 1); XPLMEnableFeature("XPLM_USE_NATIVE_PATHS", 1);
XPLMGetVersions(&xplaneVersion, NULL, NULL); XPLMGetVersions(&xplaneVersion, NULL, NULL);
toLog("Plugin using X-Plane Version " + std::to_string(xplaneVersion)); 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 /* First we must fill in the passed-in buffers to describe our
* plugin to the plugin-system. */ * plugin to the plugin-system. */
@ -95,10 +111,75 @@ PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc)
roll = XPLMFindDataRef("sim/flightmodel/position/phi"); // FLOAT roll = XPLMFindDataRef("sim/flightmodel/position/phi"); // FLOAT
quaternion = XPLMFindDataRef("sim/flightmodel/position/q"); // FLOAT[4] quaternion = XPLMFindDataRef("sim/flightmodel/position/q"); // FLOAT[4]
// Recorder configuration = std::make_unique<germanairlinesva::file::config::Config>();
recorder = toLog("Config loaded");
new germanairlinesva::gaconnector::recorder::Recorder(xplaneVersion,
connector = std::make_unique<germanairlinesva::websocket::Websocket>(
"wss://ws.hofmannnet.myhome-server.de:8000",
configuration->getUser(),
toLog); toLog);
toLog("WebSocket started");
char hash[2 * MD5LEN + 1] = "";
if (germanairlinesva::util::generateMD5(XPLANE_CUSTOM_SCENERY, hash, toLog) ==
0) {
database = std::make_unique<germanairlinesva::file::simdata::SimDatabase>(
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();
return 1; return 1;
} }
@ -107,9 +188,12 @@ PLUGIN_API void XPluginStop(void)
{ {
/* Flight Loop */ /* Flight Loop */
XPLMUnregisterFlightLoopCallback(flightLoop, nullptr); XPLMUnregisterFlightLoopCallback(flightLoop, nullptr);
/* End threads */ /* End threads */
recorder->~Recorder(); wantsExit = true;
serverThread.join();
recordingThread.join();
p.toFile("flight.rec");
toLog("Plugin stopped"); toLog("Plugin stopped");
} }
@ -130,9 +214,9 @@ PLUGIN_API void
#pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wunused-parameter"
float flightLoop(float elapsedMe, float elapsedSim, int counter, void *refcon) float flightLoop(float elapsedMe, float elapsedSim, int counter, void *refcon)
{ {
std::memset(&toSend, const std::lock_guard<std::mutex> lock(mutex);
0,
sizeof(germanairlinesva::gaconnector::websocket::data)); std::memset(&toSend, 0, sizeof(germanairlinesva::websocket::data));
toSend.pause = XPLMGetDatai(pauseIndicator); toSend.pause = XPLMGetDatai(pauseIndicator);
toSend.pBrake = XPLMGetDataf(parkingBrake); toSend.pBrake = XPLMGetDataf(parkingBrake);
@ -158,14 +242,79 @@ float flightLoop(float elapsedMe, float elapsedSim, int counter, void *refcon)
toSend.payloadKg = XPLMGetDataf(payloadKgs); toSend.payloadKg = XPLMGetDataf(payloadKgs);
toSend.totalWeightKg = XPLMGetDataf(totalWeightKgs); toSend.totalWeightKg = XPLMGetDataf(totalWeightKgs);
recorder->setData(toSend); if (!messageQueue().empty()) {
auto op = std::move(messageQueue().front());
recorder->handleMessages(); messageQueue().pop();
op();
}
return -1; return -1;
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
void serverWorker()
{
germanairlinesva::util::setThreadName("GAServerWorker");
while (!wantsExit) {
struct germanairlinesva::websocket::data copy;
{
const std::lock_guard<std::mutex> lock(mutex);
std::memcpy(&copy, &toSend, sizeof(germanairlinesva::websocket::data));
}
connector->sendData(copy);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
toLog("Server thread stopped");
}
void recordingWorker()
{
germanairlinesva::util::setThreadName("GARecordingWorker");
germanairlinesva::file::recording::RecordingEntry lastPath;
std::uint32_t segment = 0;
auto ap = (*database)["EDDF"];
auto rwys = ap.second;
while (!wantsExit) {
struct germanairlinesva::websocket::data copy;
{
const std::lock_guard<std::mutex> lock(mutex);
std::memcpy(&copy, &toSend, sizeof(germanairlinesva::websocket::data));
}
germanairlinesva::file::recording::RecordingEntry currentPath(
segment,
static_cast<std::uint16_t>(copy.alt),
static_cast<std::uint16_t>(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) void toLog(const std::string &message)
{ {
std::time_t utc = std::time(nullptr); std::time_t utc = std::time(nullptr);