7 Commits

Author SHA1 Message Date
Kilian 5af921f4cc Use Header Login
Failure Modes
Switch to use proxied wss
2022-10-22 17:16:02 +02:00
Kilian 176c43d5a6 Fix Database
Add WS Header
2022-10-22 01:42:23 +02:00
Kilian c214d473e2 Formating 2022-10-04 21:59:06 +02:00
Kilian 3a9db68e74 Convert ESP to Recorder 2022-10-04 17:47:45 +02:00
Kilian 0a150391b8 Fix std::move error 2022-10-04 02:15:39 +02:00
Kilian 396aa8d807 Initial start on Recorder 2022-10-04 01:24:15 +02:00
Kilian eafe0b18f6 Namespaces and formatting 2022-10-03 23:52:38 +02:00
26 changed files with 1159 additions and 934 deletions
+6
View File
@@ -16,3 +16,9 @@
- 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
+4
View File
@@ -1,17 +1,21 @@
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)
enable_language(RC) enable_language(RC)
# Add WIN32 to hide console window # Add WIN32 to hide console window
add_executable(germanairlinesva_esp WIN32 add_executable(germanairlinesva_esp WIN32
${socket} ${socket}
${recorder}
resources/resources-${BIT}.rc resources/resources-${BIT}.rc
simconnect.cpp simconnect.cpp
main.cpp main.cpp
) )
target_include_directories(germanairlinesva_esp PRIVATE target_include_directories(germanairlinesva_esp PRIVATE
${CMAKE_SOURCE_DIR}/esp/include
${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
+39 -6
View File
@@ -57,21 +57,50 @@ struct data {
double gForce; // G FORCE IN G double gForce; // G FORCE IN G
}; };
struct Port { struct port {
double headingTrue; // PLANE HEADING DEGREES TRUE double headingTrue; // PLANE HEADING DEGREES TRUE
double latitude; // PLANE LATITUDE double latitude; // PLANE LATITUDE
double longitude; // PLANE LONGITUDE double longitude; // PLANE LONGITUDE
}; };
struct airport {
double lat;
double lon;
char name[32];
};
struct runway {
double lat;
double lon;
float heading;
float length;
float width;
int pNum;
int pDeg;
int sNum;
int sDeg;
};
struct parking {
int type;
int name;
int suffix;
unsigned int number;
float heading;
float radius;
float x;
float z;
};
#pragma pack(pop) #pragma pack(pop)
enum DEFINITIONS { enum DEFINITIONS {
D_DATA, D_DATA,
D_FACILITY,
D_PORT, D_PORT,
}; };
enum REQUESTS { enum REQUESTS {
R_DATA, R_DATA,
R_FACILITY,
R_ACFT, R_ACFT,
R_DIALOG, R_DIALOG,
R_PORT, R_PORT,
@@ -100,7 +129,7 @@ class SimConnect
bool pausedMenu; bool pausedMenu;
bool paused; bool paused;
std::mutex mutex; std::mutex mutex;
struct germanairlinesva::websocket::data simData; struct germanairlinesva::gaconnector::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;
@@ -113,13 +142,17 @@ class SimConnect
SimConnect( SimConnect(
HWND hWnd, HWND hWnd,
std::function<void(const std::string)> toLog, std::function<void(const std::string)> toLog,
std::shared_ptr<germanairlinesva::file::config::Config> &configuration); std::shared_ptr<germanairlinesva::file::config::Config> configuration);
~SimConnect(); ~SimConnect();
bool isConnected() const; bool isConnected() const;
const std::string getVersion() const; char getVersion() const;
void getData(struct germanairlinesva::websocket::data *data); void getData(struct germanairlinesva::gaconnector::websocket::data *data);
void getStates() const; void getStates() const;
void handleMessage(); void handleMessage(std::function<void(int)> callbackOpen,
std::function<void()> callbackData);
static const std::string resolveVersion(char version);
static const std::string resolveScenery(char version);
}; };
#endif #endif
+3 -9
View File
@@ -10,25 +10,19 @@
#include <queue> #include <queue>
#include <string> #include <string>
#include "constants.h"
#include "websocket.h" #include "websocket.h"
#include <shlobj.h>
#include <stdlib.h>
#include <windows.h> #include <windows.h>
#include "config/config.hpp"
#include "constants.h"
#include "logbook/logbook.hpp"
#include "recording/recording.hpp"
#include "_simconnect.h" #include "_simconnect.h"
#include "simdata/simDatabase.hpp" #include "recorder.h"
WINBOOL addNotifyIcon(HWND hWnd); WINBOOL addNotifyIcon(HWND hWnd);
WINBOOL removeNotifyIcon(HWND hWnd); WINBOOL removeNotifyIcon(HWND hWnd);
WINBOOL createMenu(HWND hWnd); WINBOOL createMenu(HWND hWnd);
void end(HWND hwnd); void end(HWND hwnd);
void serverWorker();
void recordingWorker();
void toLog(const std::string &message); void toLog(const std::string &message);
#endif #endif
+19 -184
View File
@@ -1,22 +1,8 @@
#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;
std::unique_ptr<SimConnect> simConnect; std::unique_ptr<SimConnect> simConnect;
struct germanairlinesva::gaconnector::websocket::data toSend;
struct germanairlinesva::websocket::data toSend; germanairlinesva::gaconnector::recorder::Recorder *recorder;
germanairlinesva::file::recording::Recording p;
// The Window Procedure // The Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -48,7 +34,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
} }
case SIMCONNECT_MESSAGE: { case SIMCONNECT_MESSAGE: {
if (simConnect != nullptr && simConnect->isConnected()) { if (simConnect != nullptr && simConnect->isConnected()) {
simConnect->handleMessage(); simConnect->handleMessage(
[](int version) { recorder->loadDatabase(version); },
[]() {
germanairlinesva::gaconnector::websocket::data d;
simConnect->getStates();
simConnect->getData(&d);
recorder->setData(d);
});
} }
break; break;
} }
@@ -74,8 +67,6 @@ int WINAPI WinMain(HINSTANCE hInstance,
HWND hWnd; HWND hWnd;
MSG msg; MSG msg;
wantsExit.store(false);
// Exit if already running // Exit if already running
hWnd = FindWindow(WINDOW_CLASS, WINDOW_CLASS); hWnd = FindWindow(WINDOW_CLASS, WINDOW_CLASS);
if (hWnd != NULL) { if (hWnd != NULL) {
@@ -124,98 +115,11 @@ int WINAPI WinMain(HINSTANCE hInstance,
// Never show window // Never show window
// ShowWindow(hWnd, SHOW_OPENWINDOW); // ShowWindow(hWnd, SHOW_OPENWINDOW);
configuration = std::make_unique<germanairlinesva::file::config::Config>(); recorder = new germanairlinesva::gaconnector::recorder::Recorder(0, toLog);
toLog("Config loaded");
connector = std::make_unique<germanairlinesva::websocket::Websocket>(
"wss://ws.hofmannnet.myhome-server.de:8000",
configuration->getUser(),
toLog);
toLog("WebSocket started");
#ifndef MSFS
PWSTR folder;
HRESULT result = SHGetKnownFolderPath(FOLDERID_RoamingAppData,
KF_FLAG_DEFAULT,
NULL,
&folder);
if (SUCCEEDED(result)) {
size_t origsize = wcslen(folder) + 1;
size_t convertedChars = 0;
char *nstring = new char[origsize * 2];
wcstombs_s(&convertedChars, nstring, origsize * 2, folder, _TRUNCATE);
std::string path(nstring);
path.append("\\Microsoft\\FSX\\scenery.cfg");
toLog(path);
delete[] nstring;
CoTaskMemFree(folder);
char hash[2 * MD5LEN + 1] = "";
if (germanairlinesva::util::generateMD5(path.c_str(), hash, toLog) == 0) {
database = std::make_unique<germanairlinesva::file::simdata::SimDatabase>(
FSX_VERSION,
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");
}
#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();
// Open SimConnect // Open SimConnect
simConnect = std::make_unique<SimConnect>(hWnd, toLog, configuration); simConnect =
std::make_unique<SimConnect>(hWnd, toLog, recorder->getConfiguration());
// Thread for sending data to websocket
serverThread = std::thread(&serverWorker);
recordingThread = std::thread(&recordingWorker);
toLog("Workers started");
// The Message Loop // The Message Loop
while (GetMessage(&msg, NULL, 0, 0) > 0) { while (GetMessage(&msg, NULL, 0, 0) > 0) {
@@ -242,7 +146,7 @@ WINBOOL addNotifyIcon(HWND hWnd)
GetSystemMetrics(SM_CYSMICON), GetSystemMetrics(SM_CYSMICON),
LR_SHARED); LR_SHARED);
if (icon == NULL) { if (icon == NULL) {
toLog("error icon " + std::to_string(GetLastError())); toLog("Error icon " + std::to_string(GetLastError()));
} }
niData.cbSize = sizeof(NOTIFYICONDATA); niData.cbSize = sizeof(NOTIFYICONDATA);
niData.uVersion = NOTIFYICON_VERSION_4; niData.uVersion = NOTIFYICON_VERSION_4;
@@ -280,9 +184,12 @@ WINBOOL createMenu(HWND hWnd)
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Version: " BIT " Bit"); AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Version: " BIT " Bit");
if (simConnect->isConnected()) { if (simConnect->isConnected()) {
std::string version("Connected to Sim: "); std::string version("Connected to Sim: ");
version.append(simConnect->getVersion()); version.append(SimConnect::resolveVersion(simConnect->getVersion()));
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, version.c_str()); AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, version.c_str());
} }
if (!recorder->getSupportedState()) {
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Sim unsupported");
}
AppendMenu(hMenu, MF_SEPARATOR, NULL, NULL); AppendMenu(hMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hMenu, MF_STRING, IDM_EXIT, "Exit"); AppendMenu(hMenu, MF_STRING, IDM_EXIT, "Exit");
@@ -310,11 +217,7 @@ void end(HWND hWnd)
UnregisterClass(WINDOW_CLASS, GetModuleHandle(NULL)); UnregisterClass(WINDOW_CLASS, GetModuleHandle(NULL));
/* End threads */ /* End threads */
wantsExit = true; recorder->~Recorder();
serverThread.join();
recordingThread.join();
p.toFile("flight.rec");
// End SimConnect // End SimConnect
delete simConnect.release(); delete simConnect.release();
@@ -322,74 +225,6 @@ void end(HWND hWnd)
PostQuitMessage(0); PostQuitMessage(0);
} }
void serverWorker()
{
germanairlinesva::util::setThreadName("GAServerWorker");
while (!wantsExit) {
simConnect->getStates();
struct germanairlinesva::websocket::data *copy =
new germanairlinesva::websocket::data();
{
const std::lock_guard<std::mutex> lock(mutex);
simConnect->getData(copy);
}
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 =
new germanairlinesva::websocket::data();
{
const std::lock_guard<std::mutex> lock(mutex);
simConnect->getData(copy);
}
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);
+157 -63
View File
@@ -3,7 +3,7 @@
SimConnect::SimConnect( SimConnect::SimConnect(
HWND hWnd, HWND hWnd,
std::function<void(const std::string)> toLog, std::function<void(const std::string)> toLog,
std::shared_ptr<germanairlinesva::file::config::Config> &configuration) std::shared_ptr<germanairlinesva::file::config::Config> configuration)
: configuration(configuration), toLog(std::move(toLog)) : configuration(configuration), toLog(std::move(toLog))
{ {
HRESULT hr = SimConnect_Open(&this->simConnect, HRESULT hr = SimConnect_Open(&this->simConnect,
@@ -19,48 +19,52 @@ SimConnect::SimConnect(
this->toLog("SimConnect_Close: Connection opened"); this->toLog("SimConnect_Close: Connection opened");
// Setup SimConnect // Setup SimConnect
SimConnect_SubscribeToSystemEvent(simConnect, EVENTS::E_PAUSE, "Pause"); SimConnect_SubscribeToSystemEvent(this->simConnect,
SimConnect_SubscribeToSystemEvent(simConnect, EVENTS::E_STATUS, "Sim"); EVENTS::E_PAUSE,
"Pause");
SimConnect_SubscribeToSystemEvent(this->simConnect,
EVENTS::E_STATUS,
"Sim");
SimConnect_MapClientEventToSimEvent(simConnect, SimConnect_MapClientEventToSimEvent(this->simConnect,
EVENTS::E_TIMESEC, EVENTS::E_TIMESEC,
"CLOCK_SECONDS_ZERO"); "CLOCK_SECONDS_ZERO");
SimConnect_AddClientEventToNotificationGroup(simConnect, SimConnect_AddClientEventToNotificationGroup(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
EVENTS::E_TIMESEC, EVENTS::E_TIMESEC,
false); false);
SimConnect_SetNotificationGroupPriority(simConnect, SimConnect_SetNotificationGroupPriority(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST); SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_MapClientEventToSimEvent(simConnect, SimConnect_MapClientEventToSimEvent(this->simConnect,
EVENTS::E_TIMEMIN, EVENTS::E_TIMEMIN,
"ZULU_MINUTES_SET"); "ZULU_MINUTES_SET");
SimConnect_AddClientEventToNotificationGroup(simConnect, SimConnect_AddClientEventToNotificationGroup(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
EVENTS::E_TIMEMIN, EVENTS::E_TIMEMIN,
false); false);
SimConnect_SetNotificationGroupPriority(simConnect, SimConnect_SetNotificationGroupPriority(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST); SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_MapClientEventToSimEvent(simConnect, SimConnect_MapClientEventToSimEvent(this->simConnect,
EVENTS::E_TIMEHRS, EVENTS::E_TIMEHRS,
"ZULU_HOURS_SET"); "ZULU_HOURS_SET");
SimConnect_AddClientEventToNotificationGroup(simConnect, SimConnect_AddClientEventToNotificationGroup(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
EVENTS::E_TIMEHRS, EVENTS::E_TIMEHRS,
false); false);
SimConnect_SetNotificationGroupPriority(simConnect, SimConnect_SetNotificationGroupPriority(this->simConnect,
GROUPS::G_TIME, GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST); SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"BRAKE PARKING INDICATOR", "BRAKE PARKING INDICATOR",
"BOOL", "BOOL",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"SIM ON GROUND", "SIM ON GROUND",
"BOOL", "BOOL",
@@ -68,14 +72,14 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"EMPTY WEIGHT", "EMPTY WEIGHT",
"KILOGRAMS", "KILOGRAMS",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"TOTAL WEIGHT", "TOTAL WEIGHT",
"KILOGRAMS", "KILOGRAMS",
@@ -83,7 +87,7 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"FUEL TOTAL QUANTITY WEIGHT", "FUEL TOTAL QUANTITY WEIGHT",
"KILOGRAMS", "KILOGRAMS",
@@ -91,14 +95,14 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE HEADING DEGREES TRUE", "PLANE HEADING DEGREES TRUE",
"DEGREES", "DEGREES",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE HEADING DEGREES MAGNETIC", "PLANE HEADING DEGREES MAGNETIC",
"DEGREES", "DEGREES",
@@ -106,21 +110,21 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"GROUND VELOCITY", "GROUND VELOCITY",
"KNOTS", "KNOTS",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"AIRSPEED INDICATED", "AIRSPEED INDICATED",
"KNOTS", "KNOTS",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"AIRSPEED BARBER POLE", "AIRSPEED BARBER POLE",
"KNOTS", "KNOTS",
@@ -128,28 +132,28 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"VELOCITY WORLD Y", "VELOCITY WORLD Y",
"FEET/MINUTE", "FEET/MINUTE",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"VERTICAL SPEED", "VERTICAL SPEED",
"FEET/MINUTE", "FEET/MINUTE",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE ALTITUDE", "PLANE ALTITUDE",
"FEET", "FEET",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE ALT ABOVE GROUND", "PLANE ALT ABOVE GROUND",
"FEET", "FEET",
@@ -157,14 +161,14 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE LATITUDE", "PLANE LATITUDE",
"DEGREES", "DEGREES",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"PLANE LONGITUDE", "PLANE LONGITUDE",
"DEGREES", "DEGREES",
@@ -172,7 +176,7 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ABSOLUTE TIME", "ABSOLUTE TIME",
"SECONDS", "SECONDS",
@@ -180,28 +184,28 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:1", "ENG FUEL FLOW PPH:1",
"KILOGRAMS PER SECOND", "KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:2", "ENG FUEL FLOW PPH:2",
"KILOGRAMS PER SECOND", "KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:3", "ENG FUEL FLOW PPH:3",
"KILOGRAMS PER SECOND", "KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:4", "ENG FUEL FLOW PPH:4",
"KILOGRAMS PER SECOND", "KILOGRAMS PER SECOND",
@@ -209,21 +213,21 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"BRAKE INDICATOR", "BRAKE INDICATOR",
"POSITION", "POSITION",
SIMCONNECT_DATATYPE_INT32, SIMCONNECT_DATATYPE_INT32,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"BRAKE PARKING POSITION", "BRAKE PARKING POSITION",
"POSITION", "POSITION",
SIMCONNECT_DATATYPE_INT32, SIMCONNECT_DATATYPE_INT32,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"BRAKE LEFT POSITION", "BRAKE LEFT POSITION",
"POSITION", "POSITION",
@@ -231,7 +235,7 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"ZULU TIME", "ZULU TIME",
"SECONDS", "SECONDS",
@@ -239,7 +243,7 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
"G FORCE", "G FORCE",
"GForce", "GForce",
@@ -247,21 +251,21 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_PORT, DEFINITIONS::D_PORT,
"PLANE HEADING DEGREES TRUE", "PLANE HEADING DEGREES TRUE",
"DEGREES", "DEGREES",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_PORT, DEFINITIONS::D_PORT,
"PLANE LATITUDE", "PLANE LATITUDE",
"DEGREES", "DEGREES",
SIMCONNECT_DATATYPE_FLOAT64, SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect, SimConnect_AddToDataDefinition(this->simConnect,
DEFINITIONS::D_PORT, DEFINITIONS::D_PORT,
"PLANE LONGITUDE", "PLANE LONGITUDE",
"DEGREES", "DEGREES",
@@ -269,7 +273,67 @@ SimConnect::SimConnect(
0, 0,
SIMCONNECT_UNUSED); SIMCONNECT_UNUSED);
SimConnect_RequestDataOnSimObject(simConnect, #ifdef MSFS
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"OPEN AIRPORT");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"LATITUDE");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"LONGITUDE");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "NAME");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"OPEN RUNWAY");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"LATITUDE");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"LONGITUDE");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "HEADING");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "LENGTH");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "WIDTH");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"PRIMARY_NUMBER");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"PRIMARY_DESIGNATOR");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"SECONDARY_NUMBER");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"SECONDARY_DESIGNATOR");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"CLOSE RUNWAY");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"OPEN TAXI_PARKING");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "TYPE");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "NAME");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "SUFFIX");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "NUMBER");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "HEADING");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "RADIUS");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "BIAS_X");
SimConnect_AddToFacilityDefinition(this->simConnect, D_FACILITY, "BIAS_Z");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"CLOSE TAXI_PARKING");
SimConnect_AddToFacilityDefinition(this->simConnect,
D_FACILITY,
"CLOSE AIRPORT");
#endif
SimConnect_RequestDataOnSimObject(this->simConnect,
REQUESTS::R_DATA, REQUESTS::R_DATA,
DEFINITIONS::D_DATA, DEFINITIONS::D_DATA,
SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_OBJECT_ID_USER,
@@ -304,32 +368,17 @@ void SimConnect::getStates() const
bool SimConnect::isConnected() const { return this->connectedToSim; } bool SimConnect::isConnected() const { return this->connectedToSim; }
const std::string SimConnect::getVersion() const char SimConnect::getVersion() const { return this->version; }
{
switch (this->version) {
case MSFS_VERSION:
return "MSFS";
case FSX_VERSION:
return "FSX";
case P3D5_VERSION:
return "P3D5";
case P3D4_VERSION:
return "P3D4";
break;
case P3D3_VERSION:
return "P3D3";
default:
return "Unknown";
}
}
void SimConnect::getData(struct germanairlinesva::websocket::data *data) void SimConnect::getData(
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));
} }
void SimConnect::handleMessage() void SimConnect::handleMessage(std::function<void(int)> callbackOpen,
std::function<void()> callbackData)
{ {
SIMCONNECT_RECV *pData; SIMCONNECT_RECV *pData;
DWORD cbData; DWORD cbData;
@@ -339,6 +388,7 @@ void SimConnect::handleMessage()
switch (pData->dwID) { switch (pData->dwID) {
case SIMCONNECT_RECV_ID_OPEN: { case SIMCONNECT_RECV_ID_OPEN: {
this->handleOpen((SIMCONNECT_RECV_OPEN *)pData); this->handleOpen((SIMCONNECT_RECV_OPEN *)pData);
callbackOpen(this->version);
break; break;
} }
case SIMCONNECT_RECV_ID_EVENT: { case SIMCONNECT_RECV_ID_EVENT: {
@@ -351,8 +401,14 @@ void SimConnect::handleMessage()
} }
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: { case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {
this->handleData((SIMCONNECT_RECV_SIMOBJECT_DATA *)pData); this->handleData((SIMCONNECT_RECV_SIMOBJECT_DATA *)pData);
callbackData();
break; break;
} }
#ifdef MSFS
case SIMCONNECT_RECV_ID_FACILITY_DATA: {
this->toLog("NavData API MSFS Message received");
}
#endif
default: default:
break; break;
} }
@@ -378,7 +434,7 @@ void SimConnect::handleOpen(SIMCONNECT_RECV_OPEN *data)
this->version = FSX_VERSION; this->version = FSX_VERSION;
break; break;
case FSXSE_SUBVERSION: case FSXSE_SUBVERSION:
if (configuration->getFSXSEPath().length() > 0) { if (configuration->getPath(FSXSE_VERSION).length() > 0) {
this->version = FSXSE_VERSION; this->version = FSXSE_VERSION;
} else { } else {
this->version = FSX_VERSION; this->version = FSX_VERSION;
@@ -457,3 +513,41 @@ void SimConnect::handleData(SIMCONNECT_RECV_SIMOBJECT_DATA *data)
} }
} }
} }
const std::string SimConnect::resolveVersion(char version)
{
switch (version) {
case MSFS_VERSION:
return "MSFS";
case FSX_VERSION:
return "FSX";
case P3D5_VERSION:
return "P3D5";
case P3D4_VERSION:
return "P3D4";
break;
case P3D3_VERSION:
return "P3D3";
default:
return "Unknown";
}
}
const std::string SimConnect::resolveScenery(char version)
{
switch (version) {
case FSX_VERSION:
return FSX_SCENERY;
case FSXSE_VERSION:
return FSXSE_SCENERY;
case P3D5_VERSION:
return P3D5_SCENREY;
case P3D4_VERSION:
return P3D4_SCENREY;
break;
case P3D3_VERSION:
return P3D3_SCENREY;
default:
return "/";
}
}
+95 -18
View File
@@ -21,7 +21,13 @@ namespace file
{ {
private: private:
std::string user; std::string user;
std::string scenery; std::string XP11Scenery;
std::string XP12Scenery;
std::string FSXScenery;
std::string FSXSEScenery;
std::string P3D3Scenery;
std::string P3D4Scenery;
std::string P3D5Scenery;
std::string token; std::string token;
std::string FSXPath; std::string FSXPath;
std::string FSXSEPath; std::string FSXSEPath;
@@ -33,7 +39,13 @@ namespace file
inline void writeFile() const inline void writeFile() const
{ {
std::ofstream out(BASE_DIRECTORY CONFIG); std::ofstream out(BASE_DIRECTORY CONFIG);
out << "scenery=" << this->scenery << "\n"; out << "xp11Scenery=" << this->XP11Scenery << "\n";
out << "xp12Scenery=" << this->XP12Scenery << "\n";
out << "fsxScenery=" << this->FSXScenery << "\n";
out << "fsxSEScenery=" << this->FSXSEScenery << "\n";
out << "p3d3Scenery=" << this->P3D3Scenery << "\n";
out << "p3d4Scenery=" << this->P3D4Scenery << "\n";
out << "p3d5Scenery=" << this->P3D5Scenery << "\n";
out << "user=" << this->user << "\n"; out << "user=" << this->user << "\n";
out << "token=" << this->token << "\n"; out << "token=" << this->token << "\n";
out << "fsxPath=" << this->FSXPath << "\n"; out << "fsxPath=" << this->FSXPath << "\n";
@@ -51,12 +63,24 @@ 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 = util::split(line, '='); std::vector<std::string> fields = utilities::split(line, '=');
if (fields.size() >= 2) { if (fields.size() >= 2) {
util::trim(fields[0]); utilities::trim(fields[0]);
util::trim(fields[1]); utilities::trim(fields[1]);
if (fields[0] == "scenery") { if (fields[0] == "xp11Scenery") {
this->scenery = fields[1]; this->XP11Scenery = fields[1];
} else if (fields[0] == "xp12Scenery") {
this->XP12Scenery = fields[1];
} else if (fields[0] == "fsxScenery") {
this->FSXScenery = fields[1];
} else if (fields[0] == "fsxSEScenery") {
this->FSXSEScenery = fields[1];
} else if (fields[0] == "p3d3Scenery") {
this->P3D3Scenery = fields[1];
} else if (fields[0] == "p3d4Scenery") {
this->P3D4Scenery = fields[1];
} else if (fields[0] == "p3d5Scenery") {
this->P3D5Scenery = fields[1];
} else if (fields[0] == "user") { } else if (fields[0] == "user") {
this->user = fields[1]; this->user = fields[1];
} else if (fields[0] == "token") { } else if (fields[0] == "token") {
@@ -79,25 +103,78 @@ namespace file
in.close(); in.close();
} }
inline void updateScenery(std::string scenery) inline void updateScenery(int simVersion, std::string scenery)
{ {
this->scenery = scenery; switch (simVersion) {
case FSX_VERSION:
this->FSXScenery = scenery;
break;
case FSXSE_VERSION:
this->FSXSEScenery = scenery;
break;
case P3D3_VERSION:
this->P3D3Scenery = scenery;
break;
case P3D4_VERSION:
this->P3D4Scenery = scenery;
break;
case P3D5_VERSION:
this->P3D5Scenery = scenery;
break;
default:
if (simVersion < 12000) {
this->XP11Scenery = scenery;
} else {
this->XP12Scenery = scenery;
}
break;
}
this->writeFile(); this->writeFile();
} }
inline const std::string getUser() const { return this->user; } inline const std::string getUser() const { return this->user; }
inline const std::string getScenery() const { return this->scenery; } inline const std::string getScenery(int simVersion) const
inline const std::string getToken() const { return this->token; }
inline const std::string getFSXPath() const { return this->FSXPath; }
inline const std::string getFSXSEPath() const
{ {
return this->FSXSEPath; switch (simVersion) {
case FSX_VERSION:
return this->FSXScenery;
case FSXSE_VERSION:
return this->FSXSEScenery;
case P3D3_VERSION:
return this->P3D3Scenery;
case P3D4_VERSION:
return this->P3D4Scenery;
case P3D5_VERSION:
return this->P3D5Scenery;
default:
if (simVersion < 12000) {
return this->XP11Scenery;
} else {
return this->XP12Scenery;
}
}
}
inline const std::string getToken() const { return this->token; }
inline const std::string getPath(int simVersion) const
{
switch (simVersion) {
case FSX_VERSION:
return this->FSXPath;
case FSXSE_VERSION:
return this->FSXSEPath;
case P3D3_VERSION:
return this->P3D3Path;
case P3D4_VERSION:
return this->P3D4Path;
case P3D5_VERSION:
return this->P3D5Path;
case MSFS_VERSION:
return this->MSFSPath;
default:
return "/";
}
} }
inline const std::string getP3D3Path() const { return this->P3D3Path; }
inline const std::string getP3D4Path() const { return this->P3D4Path; }
inline const std::string getP3D5Path() const { return this->P3D5Path; }
inline const std::string getMSFSPath() const { return this->MSFSPath; }
}; };
} // namespace config } // namespace config
} // namespace file } // namespace file
+1 -1
View File
@@ -117,7 +117,7 @@ namespace file
public: public:
inline Logbook() inline Logbook()
{ {
if (util::fileExists(BASE_DIRECTORY LOGBOOK)) { if (utilities::fileExists(BASE_DIRECTORY LOGBOOK)) {
this->fromFile(); this->fromFile();
} }
} }
+4 -4
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_FILE_RECORDINGENTRY_H #ifndef GERMANAIRLINESVA_FILE_RECORDING_RECORDINGENTRY_H
#define GERMANAIRLINESVA_FILE_RECORDINGENTRY_H #define GERMANAIRLINESVA_FILE_RECORDING_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 geodata::point coordinates = {NAN, NAN}; struct utilities::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 geodata::point coordinates) struct utilities::geodata::point coordinates)
: time(time), altitude(altitude), groundSpeed(groundSpeed), : time(time), altitude(altitude), groundSpeed(groundSpeed),
coordinates(coordinates) coordinates(coordinates)
{ {
+4 -4
View File
@@ -32,7 +32,7 @@ namespace file
{ {
private: private:
std::string designator; std::string designator;
struct geodata::point center; struct utilities::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 geodata::point center, struct utilities::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(geodata::point coordinates) const inline bool contains(utilities::geodata::point coordinates) const
{ {
return geodata::distanceEarthP(this->center, coordinates); return utilities::geodata::distanceEarthP(this->center, coordinates);
} }
inline const std::string to_string() const inline const std::string to_string() const
+15 -13
View File
@@ -34,7 +34,7 @@ namespace file
{ {
private: private:
std::string designator; std::string designator;
struct geodata::box bounds; struct utilities::geodata::box bounds;
std::uint8_t width; std::uint8_t width;
std::uint16_t length; std::uint16_t length;
double trueHeading; double trueHeading;
@@ -49,49 +49,51 @@ namespace file
double width) double width)
: designator(designator), width(width) : designator(designator), width(width)
{ {
this->length = geodata::distanceEarthD(latitudeStart, this->length = utilities::geodata::distanceEarthD(latitudeStart,
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd); longitudeEnd);
this->trueHeading = geodata::bearingDD(latitudeStart, this->trueHeading = utilities::geodata::bearingDD(latitudeStart,
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd); longitudeEnd);
this->bounds = this->bounds = utilities::geodata::calculateBoxDD(
geodata::calculateBoxDD({latitudeStart, longitudeStart}, {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 geodata::point start, struct utilities::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)
{ {
geodata::point end = utilities::geodata::point end =
geodata::calculatePointDD(start, trueHeading, length); utilities::geodata::calculatePointDD(start, trueHeading, length);
this->bounds = this->bounds = utilities::geodata::calculateBoxDD(start,
geodata::calculateBoxDD(start, end, trueHeading, width); end,
trueHeading,
width);
}; };
// From database // From database
inline Runway(std::string designator, inline Runway(std::string designator,
struct geodata::box bounds, struct utilities::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 geodata::point point) const inline bool containsPoint(const utilities::geodata::point point) const
{ {
size_t j = 3; size_t j = 3;
bool c = false; bool c = false;
std::vector<geodata::point> poly{this->bounds.topLeft, std::vector<utilities::geodata::point> poly{this->bounds.topLeft,
this->bounds.topRight, this->bounds.topRight,
this->bounds.bottomRight, this->bounds.bottomRight,
this->bounds.bottomLeft}; this->bounds.bottomLeft};
+64 -81
View File
@@ -19,7 +19,7 @@
#ifdef XP #ifdef XP
#include "simdata/simdataXP.hpp" #include "simdata/simdataXP.hpp"
#endif #endif
#ifndef MSFS #if not defined(XP) && not defined(MSFS)
#include "simdata/simdataESP.hpp" #include "simdata/simdataESP.hpp"
#endif #endif
@@ -61,7 +61,8 @@ 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 geodata::point center = read<struct geodata::point>(in); struct utilities::geodata::point center =
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,
@@ -73,7 +74,8 @@ 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 geodata::box bounds = read<struct geodata::box>(in); struct utilities::geodata::box bounds =
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);
@@ -89,10 +91,8 @@ namespace file
in.close(); in.close();
} }
inline void fromFile(const char *file) inline void fromFile(const char *path)
{ {
std::string path(BASE_DIRECTORY);
path.append(file);
std::ifstream in(path, std::ifstream::binary); std::ifstream in(path, std::ifstream::binary);
std::string ident = readString(in, 4); std::string ident = readString(in, 4);
@@ -106,82 +106,8 @@ namespace file
} }
} }
public: inline void toFile(const char *path) const
inline SimDatabase(int simVersion,
const char *hash,
std::shared_ptr<config::Config> &configuration,
std::function<void(const std::string)> toLog)
{ {
if (strcmp(configuration->getScenery().c_str(), hash) != 0 ||
!util::fileExists(BASE_DIRECTORY SIMDATABASE)) {
#ifdef XP
scan(simVersion < 12000 ? XPLANE11_BASE_SCENERY
: XPLANE12_BASE_SCENERY,
XPLANE_CUSTOM_SCENERY,
BASE_DIRECTORY "log.txt",
airports);
#endif
#ifndef MSFS
scan(BASE_DIRECTORY MAKERWYS_R5,
BASE_DIRECTORY MAKERWYS_G5,
BASE_DIRECTORY "db_log.txt",
airports);
#endif
configuration->updateScenery(hash);
#ifdef XP
this->toFile(SIMDATABASE);
#endif
#ifndef MSFS
switch (simVersion) {
case FSX_VERSION:
this->toFile(FSX_PREFIX SIMDATABASE);
break;
case FSXSE_VERSION:
this->toFile(FSXSE_PREFIX SIMDATABASE);
break;
case P3D3_VERSION:
this->toFile(P3D3_PREFIX SIMDATABASE);
break;
case P3D4_VERSION:
this->toFile(P3D4_PREFIX SIMDATABASE);
break;
case P3D5_VERSION:
this->toFile(P3D5_PREFIX SIMDATABASE);
break;
}
#endif
toLog("Sim Database updated");
} else {
#ifdef XP
this->fromFile(SIMDATABASE);
#endif
#ifndef MSFS
switch (simVersion) {
case FSX_VERSION:
this->fromFile(FSX_PREFIX SIMDATABASE);
break;
case FSXSE_VERSION:
this->fromFile(FSXSE_PREFIX SIMDATABASE);
break;
case P3D3_VERSION:
this->fromFile(P3D3_PREFIX SIMDATABASE);
break;
case P3D4_VERSION:
this->fromFile(P3D4_PREFIX SIMDATABASE);
break;
case P3D5_VERSION:
this->fromFile(P3D5_PREFIX SIMDATABASE);
break;
}
#endif
toLog("Sim Database loaded");
}
}
inline void toFile(const char *file) const
{
std::string path(BASE_DIRECTORY);
path.append(file);
std::ofstream out(path, std::fstream::binary); std::ofstream out(path, std::fstream::binary);
// File Header // File Header
@@ -213,6 +139,63 @@ namespace file
out.close(); out.close();
} }
inline const char *resolveFilename(int simVersion) const
{
switch (simVersion) {
case FSX_VERSION:
return BASE_DIRECTORY FSX_PREFIX SIMDATABASE;
case FSXSE_VERSION:
return BASE_DIRECTORY FSXSE_PREFIX SIMDATABASE;
case P3D3_VERSION:
return BASE_DIRECTORY P3D3_PREFIX SIMDATABASE;
case P3D4_VERSION:
return BASE_DIRECTORY P3D4_PREFIX SIMDATABASE;
case P3D5_VERSION:
return BASE_DIRECTORY P3D5_PREFIX SIMDATABASE;
case MSFS_VERSION:
return "NONE";
default:
return BASE_DIRECTORY SIMDATABASE;
}
}
public:
inline SimDatabase(int simVersion,
const char *hash,
std::shared_ptr<config::Config> &configuration,
std::function<void(const std::string)> toLog)
{
if (strcmp(configuration->getScenery(simVersion).c_str(), hash) !=
0 ||
!utilities::fileExists(resolveFilename(simVersion))) {
#ifdef XP
scan(simVersion < 12000 ? XPLANE11_BASE_SCENERY
: XPLANE12_BASE_SCENERY,
XPLANE_CUSTOM_SCENERY,
BASE_DIRECTORY "log.txt",
airports);
#endif
#ifndef MSFS
scan(BASE_DIRECTORY MAKERWYS_R5,
BASE_DIRECTORY MAKERWYS_G5,
BASE_DIRECTORY "db_log.txt",
airports);
#endif
configuration->updateScenery(simVersion, hash);
#ifndef MSFS
this->toFile(resolveFilename(simVersion));
#endif
toLog("Sim Database updated");
} else {
#ifndef MSFS
this->fromFile(resolveFilename(simVersion));
#endif
toLog("Sim Database loaded");
}
}
inline std::size_t getCount() const { return this->airports.size(); } inline std::size_t getCount() const { return this->airports.size(); }
inline const std::pair<const std::vector<Gate>, inline const std::pair<const std::vector<Gate>,
+9 -8
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAXP_H #ifndef GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAESP_H
#define GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAXP_H #define GERMANAIRLINESVA_FILE_SIMDATA_SIMDATAESP_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 = util::split(line, ','); std::vector<std::string> fields = utilities::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,12 +85,13 @@ namespace file
designator = "0" + designator; designator = "0" + designator;
} }
struct geodata::point start = {std::stod(fields[2]), struct utilities::geodata::point start = {std::stod(fields[2]),
std::stod(fields[3])}; std::stod(fields[3])};
tmpRunways.emplace_back(designator, tmpRunways.emplace_back(
designator,
start, start,
geodata::toMetre(std::stod(fields[8])), utilities::geodata::toMetre(std::stod(fields[8])),
geodata::toMetre(std::stod(fields[6])), utilities::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;
@@ -98,7 +99,7 @@ namespace file
currentIcao = nullptr; currentIcao = nullptr;
while (std::getline(gates, line)) { while (std::getline(gates, line)) {
std::vector<std::string> fields = util::split(line, ','); std::vector<std::string> fields = utilities::split(line, ',');
// New ICAO // New ICAO
if (currentIcao != nullptr && *currentIcao != fields[0]) { if (currentIcao != nullptr && *currentIcao != fields[0]) {
tmpAirportGates[*currentIcao] = tmpGates; tmpAirportGates[*currentIcao] = tmpGates;
+4 -3
View File
@@ -79,8 +79,9 @@ namespace file
int validCount = 0; int validCount = 0;
while (std::getline(infile, line)) { while (std::getline(infile, line)) {
std::vector<std::string> fields = util::split(line, ' '); std::vector<std::string> fields = utilities::split(line, ' ');
fields = util::select_T<std::string>(fields, [](const std::string &s) { fields =
utilities::select_T<std::string>(fields, [](const std::string &s) {
return s.length() > 0; return s.length() > 0;
}); });
@@ -173,7 +174,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 = util::rtrim_copy(line.substr(pos + 13)) + std::string path = utilities::rtrim_copy(line.substr(pos + 13)) +
"Earth nav data/apt.dat"; "Earth nav data/apt.dat";
packs.emplace_back(path); packs.emplace_back(path);
} }
+1 -1
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' GLOBIGNORE='**/XPLM/**:XPLM/**:**/XPLM:**/ixwebsocket/**:ixwebsocket/**:**/ixwebsocket:**/nlohmann/**:nlohmann/**:**/nlohmann:**/XPSDK/**:XPSDK/**:**/XPSDK:**/build*/**:build*/**:**/build*:**/openSSL/**:openSSL/**:**/openSSL:**/SimConnect/**:SimConnect/**:**/SimConnect'
clang-format -verbose -i **/*.cpp clang-format -verbose -i **/*.cpp
clang-format -verbose -i **/*.h clang-format -verbose -i **/*.h
+77
View File
@@ -0,0 +1,77 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H
#define GERMANAIRLINESVA_GACONNECTOR_RECORDER_RECORDER_H
#include <atomic>
#include <functional>
#include <mutex>
#include <queue>
#include <thread>
#include "constants.h"
#include "websocket.h"
#if defined(IBM) && not defined(XP)
#include "_simconnect.h"
#include <shlobj.h>
#include <stdlib.h>
#include <windows.h>
#endif
#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;
bool simSupported = false;
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();
std::shared_ptr<file::config::Config> getConfiguration() const;
void loadDatabase(int simVersion);
bool getSupportedState() const;
};
} // namespace recorder
} // namespace gaconnector
} // namespace germanairlinesva
#endif
+209
View File
@@ -0,0 +1,209 @@
#include "include/recorder.h"
namespace germanairlinesva
{
namespace gaconnector
{
namespace recorder
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
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
this->loadDatabase(simVersion);
#endif
// WebSocket
this->connector =
std::make_unique<websocket::Websocket>(WEBSOCKET_ADDRESS,
this->configuration->getUser(),
this->configuration->getToken(),
this->toLog);
this->toLog("WebSocket started");
// For Testing
#ifdef XP
this->test();
#endif
// Thread for sending data to websocket
this->serverThread = std::thread(&Recorder::serverWorker, this);
this->recordingThread = std::thread(&Recorder::recordingWorker, this);
this->toLog("Workers started");
}
#pragma clang diagnostic pop
Recorder::~Recorder()
{
this->wantsExit.store(true);
this->serverThread.join();
this->recordingThread.join();
}
void Recorder::setData(websocket::data &data)
{
const std::lock_guard<std::mutex> lock(this->mutex);
std::memcpy(&this->toSend, &data, sizeof(websocket::data));
}
void Recorder::handleMessages()
{
const std::lock_guard<std::mutex> lock(this->mutex);
if (!this->messageQueue().empty()) {
auto op = std::move(this->messageQueue().front());
this->messageQueue().pop();
op();
}
}
std::shared_ptr<file::config::Config> Recorder::getConfiguration() const
{
return this->configuration;
}
void Recorder::loadDatabase(int simVersion)
{
#ifdef XP
char hash[2 * MD5LEN + 1] = "";
if (utilities::generateMD5(XPLANE_CUSTOM_SCENERY, hash, this->toLog) ==
0) {
this->database =
std::make_unique<file::simdata::SimDatabase>(simVersion,
hash,
this->configuration,
this->toLog);
}
#endif
#if defined(IBM) && not defined(XP)
if (simVersion == MSFS_VERSION) {
this->simSupported = strcmp(BIT, "64") == 0;
return;
}
this->toLog("Loading database for " +
SimConnect::resolveVersion(simVersion));
PWSTR folder;
HRESULT result = SHGetKnownFolderPath(FOLDERID_RoamingAppData,
KF_FLAG_DEFAULT,
NULL,
&folder);
if (SUCCEEDED(result)) {
size_t origsize = wcslen(folder) + 1;
size_t convertedChars = 0;
char *nstring = new char[origsize * 2];
wcstombs_s(&convertedChars, nstring, origsize * 2, folder, _TRUNCATE);
std::string path(nstring);
path.append(SimConnect::resolveScenery(simVersion));
this->toLog("Scenery path: " + path);
delete[] nstring;
CoTaskMemFree(folder);
char hash[2 * MD5LEN + 1] = "";
if (utilities::generateMD5(path.c_str(), hash, toLog) == 0) {
this->database =
std::make_unique<file::simdata::SimDatabase>(simVersion,
hash,
this->configuration,
this->toLog);
}
this->test();
}
#endif
// Only here can we be sure to have a supported sim
this->simSupported = true;
}
bool Recorder::getSupportedState() const { return this->simSupported; }
void Recorder::serverWorker()
{
utilities::setThreadName("GAServerWorker");
while (!wantsExit) {
struct websocket::data copy;
{
const std::lock_guard<std::mutex> lock(this->mutex);
std::memcpy(&copy, &this->toSend, sizeof(websocket::data));
}
this->connector->sendData(copy);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
this->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(this->mutex);
std::memcpy(&copy, &this->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");
this->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
}
} // namespace recorder
} // namespace gaconnector
} // namespace germanairlinesva
+10 -2
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_CONSTANTS_H #ifndef GERMANAIRLINESVA_UTILITIES_CONSTANTS_H
#define GERMANAIRLINESVA_GACONNECTOR_CONSTANTS_H #define GERMANAIRLINESVA_UTILITIES_CONSTANTS_H
#ifdef XP #ifdef XP
#define BASE_DIRECTORY "Resources/plugins/GAConnector/" #define BASE_DIRECTORY "Resources/plugins/GAConnector/"
@@ -63,6 +63,12 @@
#define P3D5_VERSION 5 #define P3D5_VERSION 5
#define MSFS_VERSION 11 #define MSFS_VERSION 11
#define FSX_SCENERY "\\Microsoft\\FSX\\scenery.cfg"
#define FSXSE_SCENERY "\\Microsoft\\FSX-SE\\scenery.cfg"
#define P3D3_SCENREY "\\Lockheed Martin\\Prepar3D V3\\scenery.cfg"
#define P3D4_SCENREY "\\Lockheed Martin\\Prepar3D V4\\scenery.cfg"
#define P3D5_SCENREY "\\Lockheed Martin\\Prepar3D V5\\scenery.cfg"
// Not supported // Not supported
#define FSXRTM_SUBVERSION 60905 #define FSXRTM_SUBVERSION 60905
#define FSSXSP1_SUBVERRSION 61242 #define FSSXSP1_SUBVERRSION 61242
@@ -73,4 +79,6 @@
// Must be differentiated due to SxS Install // Must be differentiated due to SxS Install
#define FSXSE_SUBVERSION 62615 #define FSXSE_SUBVERSION 62615
#define WEBSOCKET_ADDRESS "wss://wsecho.hofmannnet.myhome-server.de/ws"
#endif #endif
+15 -8
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_GEODATA_H #ifndef GERMANAIRLINESVA_UTILITIES_GEODATA_H
#define GERMANAIRLINESVA_GACONNECTOR_GEODATA_H #define GERMANAIRLINESVA_UTILITIES_GEODATA_H
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#define BUFSIZE 1024 #define BUFSIZE 1024
@@ -9,6 +9,8 @@
#include <cmath> #include <cmath>
namespace germanairlinesva namespace germanairlinesva
{
namespace utilities
{ {
namespace geodata namespace geodata
{ {
@@ -91,7 +93,8 @@ namespace geodata
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 * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v)); return 2.0 * EARTH_M *
asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
} }
// Input in degrees, Output in metres // Input in degrees, Output in metres
@@ -104,7 +107,8 @@ namespace geodata
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 * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v)); return 2.0 * EARTH_M *
asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
} }
// Input and Output in degrees // Input and Output in degrees
@@ -169,7 +173,8 @@ namespace geodata
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(newLatitude)); std::sin(coordinates.latitude) *
std::sin(newLatitude));
return {toDegrees(newLatitude), toDegrees(newLongitude)}; return {toDegrees(newLatitude), toDegrees(newLongitude)};
} }
@@ -190,7 +195,8 @@ namespace geodata
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(newLatitude)); std::sin(coordinates.latitude) *
std::sin(newLatitude));
return {newLatitude, newLongitude}; return {newLatitude, newLongitude};
} }
@@ -201,7 +207,8 @@ namespace geodata
double length, double length,
double width) double width)
{ {
struct point primaryCenter = calculatePointDR(center, bearing, -length / 2); struct point primaryCenter =
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 =
@@ -237,8 +244,8 @@ namespace geodata
return {primaryTop, secondaryTop, secondaryBottom, primaryBottom}; return {primaryTop, secondaryTop, secondaryBottom, primaryBottom};
} }
} // namespace geodata } // namespace geodata
} // namespace utilities
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif
+4 -4
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_UTIL_H #ifndef GERMANAIRLINESVA_UTILITIES_UTIL_H
#define GERMANAIRLINESVA_GACONNECTOR_UTIL_H #define GERMANAIRLINESVA_UTILITIES_UTIL_H
#define BUFSIZE 1024 #define BUFSIZE 1024
#define MD5LEN 16 #define MD5LEN 16
@@ -36,7 +36,7 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace util namespace utilities
{ {
template <typename T> template <typename T>
static inline std::vector<T> static inline std::vector<T>
@@ -294,7 +294,7 @@ namespace util
return result; return result;
} }
} // namespace util } // namespace utilities
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif
+23 -3
View File
@@ -1,9 +1,11 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_SOCKET_TYPES_H #ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_TYPES_H
#define GERMANAIRLINESVA_GACONNECTOR_SOCKET_TYPES_H #define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_TYPES_H
#include <cstdint> #include <cstdint>
namespace germanairlinesva namespace germanairlinesva
{
namespace gaconnector
{ {
namespace websocket namespace websocket
{ {
@@ -32,7 +34,17 @@ namespace websocket
float totalWeightKg = 0; float totalWeightKg = 0;
}; };
enum commands { PROCESS, SAVE, LOAD, TEXT, TIME, UNPAUSE, PAUSE, PORT, END }; enum commands {
PROCESS,
SAVE,
LOAD,
TEXT,
TIME,
UNPAUSE,
PAUSE,
PORT,
END
};
struct command_base { struct command_base {
enum commands type; enum commands type;
@@ -44,8 +56,16 @@ namespace websocket
float trueHeading; float trueHeading;
}; };
enum failures {
NONE,
AUTH,
DUPLICATESIM,
OTHER,
};
#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
+9 -2
View File
@@ -1,5 +1,5 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_H #ifndef GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_WEBSOCKET_H
#define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_H #define GERMANAIRLINESVA_GACONNECTOR_WEBSOCKET_WEBSOCKET_H
#define BUFSIZE 1024 #define BUFSIZE 1024
#define MD5LEN 16 #define MD5LEN 16
@@ -19,28 +19,35 @@
#include <utility> #include <utility>
namespace germanairlinesva namespace germanairlinesva
{
namespace gaconnector
{ {
namespace websocket namespace websocket
{ {
class Websocket class Websocket
{ {
private: private:
bool isLoggedIn = false;
enum failures failureMode = failures::NONE;
char lastPath[513] = ""; char lastPath[513] = "";
char lastHash[2 * MD5LEN + 1] = ""; char lastHash[2 * MD5LEN + 1] = "";
ix::WebSocket *webSocket = nullptr; ix::WebSocket *webSocket = nullptr;
std::string host; std::string host;
std::string user; std::string user;
std::string token;
std::function<void(const std::string)> toLog; std::function<void(const std::string)> toLog;
public: public:
Websocket(std::string host, Websocket(std::string host,
std::string user, std::string user,
std::string token,
std::function<void(const std::string)> toLog); std::function<void(const std::string)> toLog);
~Websocket(); ~Websocket();
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
+49 -26
View File
@@ -1,13 +1,16 @@
#include "include/websocket.h" #include "include/websocket.h"
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::string token,
std::function<void(const std::string)> toLog) std::function<void(const std::string)> toLog)
: host(host), user(user), toLog(std::move(toLog)) : host(host), user(user), token(token), toLog(std::move(toLog))
{ {
#ifdef IBM #ifdef IBM
// Required on Windows // Required on Windows
@@ -15,6 +18,11 @@ namespace websocket
#endif #endif
this->webSocket = new ix::WebSocket(); this->webSocket = new ix::WebSocket();
this->webSocket->setExtraHeaders({
{"origin", "GAClient"},
{"authentication", "Bearer " + this->token},
{"user", this->user},
});
this->webSocket->enableAutomaticReconnection(); this->webSocket->enableAutomaticReconnection();
this->webSocket->setUrl(host); this->webSocket->setUrl(host);
this->webSocket->setOnMessageCallback( this->webSocket->setOnMessageCallback(
@@ -39,44 +47,57 @@ namespace websocket
if (msg->type == ix::WebSocketMessageType::Open) { if (msg->type == ix::WebSocketMessageType::Open) {
std::stringstream debug_msg; std::stringstream debug_msg;
debug_msg << std::endl << "New connection" << std::endl; debug_msg << "New connection" << std::endl;
debug_msg << "Uri: " << msg->openInfo.uri << std::endl; debug_msg << "\tUri: " << msg->openInfo.uri << std::endl;
debug_msg << "Headers:" << std::endl; debug_msg << "\tHeaders:" << std::endl;
for (const auto &it : msg->openInfo.headers) { for (const auto &it : msg->openInfo.headers) {
debug_msg << it.first << ": " << it.second << std::endl; debug_msg << "\t\t" << it.first << ": " << it.second << std::endl;
} }
this->toLog(debug_msg.str()); this->toLog(debug_msg.str());
this->webSocket->send("MASTER:" + user); this->toLog("Connected as " + user);
this->toLog("Connecting as " + user); this->isLoggedIn = true;
this->failureMode = failures::NONE;
} else if (msg->type == ix::WebSocketMessageType::Close) { } else if (msg->type == ix::WebSocketMessageType::Close) {
if (msg->closeInfo.reason.compare("DUPLICATE") == 0) {
this->webSocket->disableAutomaticReconnection();
this->toLog("Disconnected due to beeing a duplicate simualtor");
} else {
std::stringstream debug_msg; std::stringstream debug_msg;
debug_msg << std::endl << "Connection closed" << std::endl; debug_msg << "Connection closed" << std::endl;
debug_msg << "Code: " << msg->closeInfo.code << std::endl; debug_msg << "\tCode: " << msg->closeInfo.code << std::endl;
debug_msg << "Reason: " << msg->closeInfo.reason << std::endl; debug_msg << "\tReason: " << msg->closeInfo.reason << std::endl;
debug_msg << "Remote: " << msg->closeInfo.remote << std::endl; debug_msg << "\tRemote: " << msg->closeInfo.remote << std::endl;
this->toLog(debug_msg.str()); this->toLog(debug_msg.str());
} this->isLoggedIn = false;
} else if (msg->type == ix::WebSocketMessageType::Error) { } else if (msg->type == ix::WebSocketMessageType::Error) {
std::stringstream debug_msg; std::stringstream debug_msg;
debug_msg << std::endl << "Connection error" << std::endl; debug_msg << "Connection error" << std::endl;
debug_msg << "Decompression: " << msg->errorInfo.decompressionError debug_msg << "\tDecompression: " << msg->errorInfo.decompressionError
<< std::endl; << std::endl;
debug_msg << "HTTP status: " << msg->errorInfo.http_status << std::endl; debug_msg << "\tHTTP status: " << msg->errorInfo.http_status
debug_msg << "Reason: " << msg->errorInfo.reason << std::endl; << std::endl;
debug_msg << "Retries: " << msg->errorInfo.retries << std::endl; debug_msg << "\tReason: " << msg->errorInfo.reason << std::endl;
debug_msg << "Wait time: " << msg->errorInfo.wait_time << std::endl; debug_msg << "\tRetries: " << msg->errorInfo.retries << std::endl;
debug_msg << "\tWait time: " << msg->errorInfo.wait_time << std::endl;
if (msg->errorInfo.http_status == 401) {
this->webSocket->disableAutomaticReconnection();
this->toLog("Disabling automatic reconnection due to auth failure");
this->failureMode = failures::AUTH;
} else if (msg->errorInfo.http_status == 500 &&
msg->errorInfo.reason.find("Duplicate") !=
std::string::npos) {
this->webSocket->disableAutomaticReconnection();
this->toLog("Disabling automatic reconnection due to duplicate");
this->failureMode = failures::DUPLICATESIM;
} else {
this->failureMode = failures::OTHER;
}
this->toLog(debug_msg.str()); this->toLog(debug_msg.str());
this->isLoggedIn = false;
} else if (msg->type == ix::WebSocketMessageType::Message) { } else if (msg->type == ix::WebSocketMessageType::Message) {
if (!msg->str.empty()) { if (!msg->str.empty()) {
this->toLog(msg->str); this->toLog(msg->str);
@@ -88,8 +109,8 @@ namespace websocket
{ {
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 (util::generateMD5(d.path, this->lastHash, this->toLog)) { if (utilities::generateMD5(d.path, this->lastHash, this->toLog)) {
strcpy(this->lastHash, "NOT SET"); strcpy(this->lastHash, "NO HASH");
} }
} }
@@ -101,6 +122,7 @@ namespace websocket
{"truHdg", d.truHdg}, {"truHdg", d.truHdg},
{"totFuel", d.totFuelKg}, {"totFuel", d.totFuelKg},
{"fuelFlow", d.ff}, {"fuelFlow", d.ff},
{"path", d.path},
{"hash", this->lastHash}, {"hash", this->lastHash},
}; };
@@ -111,4 +133,5 @@ namespace websocket
} }
} }
} // namespace websocket } // namespace websocket
} // namespace gaconnector
} // namespace germanairlinesva } // namespace germanairlinesva
+4
View File
@@ -1,12 +1,16 @@
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}/xplugin/include
${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
+2 -13
View File
@@ -1,24 +1,13 @@
#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 "websocket.h" #include "recorder.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"
+15 -164
View File
@@ -1,20 +1,5 @@
#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;
@@ -43,22 +28,21 @@ XPLMDataRef pitch;
XPLMDataRef roll; XPLMDataRef roll;
XPLMDataRef quaternion; XPLMDataRef quaternion;
struct germanairlinesva::websocket::data toSend; struct germanairlinesva::gaconnector::websocket::data toSend;
germanairlinesva::file::recording::Recording p; germanairlinesva::gaconnector::recorder::Recorder *recorder;
/* /*
* 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. */
@@ -111,75 +95,10 @@ 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]
configuration = std::make_unique<germanairlinesva::file::config::Config>(); // Recorder
toLog("Config loaded"); recorder =
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;
} }
@@ -188,12 +107,9 @@ PLUGIN_API void XPluginStop(void)
{ {
/* Flight Loop */ /* Flight Loop */
XPLMUnregisterFlightLoopCallback(flightLoop, nullptr); XPLMUnregisterFlightLoopCallback(flightLoop, nullptr);
/* End threads */
wantsExit = true;
serverThread.join();
recordingThread.join();
p.toFile("flight.rec"); /* End threads */
recorder->~Recorder();
toLog("Plugin stopped"); toLog("Plugin stopped");
} }
@@ -214,9 +130,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)
{ {
const std::lock_guard<std::mutex> lock(mutex); std::memset(&toSend,
0,
std::memset(&toSend, 0, sizeof(germanairlinesva::websocket::data)); sizeof(germanairlinesva::gaconnector::websocket::data));
toSend.pause = XPLMGetDatai(pauseIndicator); toSend.pause = XPLMGetDatai(pauseIndicator);
toSend.pBrake = XPLMGetDataf(parkingBrake); toSend.pBrake = XPLMGetDataf(parkingBrake);
@@ -242,79 +158,14 @@ 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);
if (!messageQueue().empty()) { recorder->setData(toSend);
auto op = std::move(messageQueue().front());
messageQueue().pop(); recorder->handleMessages();
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);