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
+27 -25
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,52 +49,54 @@ 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};
for (size_t i = 0; i < poly.size(); i++) { for (size_t i = 0; i < poly.size(); i++) {
if ((point.latitude == poly[i].latitude) && if ((point.latitude == poly[i].latitude) &&
+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>,
+12 -11
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,20 +85,21 @@ 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(
start, designator,
geodata::toMetre(std::stod(fields[8])), start,
geodata::toMetre(std::stod(fields[6])), utilities::geodata::toMetre(std::stod(fields[8])),
std::stod(fields[5]) + std::stod(fields[9])); utilities::geodata::toMetre(std::stod(fields[6])),
std::stod(fields[5]) + std::stod(fields[9]));
log << "\t<RUNWAY> " << line << std::endl; log << "\t<RUNWAY> " << line << std::endl;
} }
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;
+6 -5
View File
@@ -79,10 +79,11 @@ 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 =
return s.length() > 0; utilities::select_T<std::string>(fields, [](const std::string &s) {
}); return s.length() > 0;
});
if (fields.empty()) if (fields.empty())
continue; continue;
@@ -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
+202 -195
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
@@ -10,235 +10,242 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace geodata namespace utilities
{ {
namespace geodata
{
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct point { struct point {
double latitude; double latitude;
double longitude; double longitude;
}; };
#pragma pack(pop) #pragma pack(pop)
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct box { struct box {
struct point topLeft; struct point topLeft;
struct point topRight; struct point topRight;
struct point bottomRight; struct point bottomRight;
struct point bottomLeft; struct point bottomLeft;
}; };
#pragma pack(pop) #pragma pack(pop)
static inline double toMetre(double value) { return value * 0.3048; } static inline double toMetre(double value) { return value * 0.3048; }
static inline double toFeet(double value) { return value * 3.280839895; } static inline double toFeet(double value) { return value * 3.280839895; }
static inline double toDegrees(double value) { return value * 180 / M_PI; } static inline double toDegrees(double value) { return value * 180 / M_PI; }
static inline double toRadians(double value) { return value * M_PI / 180; } static inline double toRadians(double value) { return value * M_PI / 180; }
static inline double normalizeD(double value) static inline double normalizeD(double value)
{ {
return fmod(value + 360, 360); return fmod(value + 360, 360);
} }
static inline double normalizeR(double value) static inline double normalizeR(double value)
{ {
return value < 0 ? 2 * M_PI + value : value; return value < 0 ? 2 * M_PI + value : value;
} }
// Input and Output in degrees // Input and Output in degrees
static inline double bearingDD(double fromLatitude, static inline double bearingDD(double fromLatitude,
double fromLongitude, double fromLongitude,
double toLatitude, double toLatitude,
double toLongitude) double toLongitude)
{ {
double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) * double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) *
cos(toRadians(toLatitude)); cos(toRadians(toLatitude));
double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) - double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) -
sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) * sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) *
cos(toRadians(toLongitude) - toRadians(fromLongitude)); cos(toRadians(toLongitude) - toRadians(fromLongitude));
return normalizeD(toDegrees(atan2(y, x))); return normalizeD(toDegrees(atan2(y, x)));
} }
// Input in degrees, Output in radians // Input in degrees, Output in radians
static inline double bearingDR(double fromLatitude, static inline double bearingDR(double fromLatitude,
double fromLongitude, double fromLongitude,
double toLatitude, double toLatitude,
double toLongitude) double toLongitude)
{ {
double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) * double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) *
cos(toRadians(toLatitude)); cos(toRadians(toLatitude));
double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) - double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) -
sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) * sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) *
cos(toRadians(toLongitude) - toRadians(fromLongitude)); cos(toRadians(toLongitude) - toRadians(fromLongitude));
return normalizeR(atan2(y, x)); return normalizeR(atan2(y, x));
} }
// Input in degrees, Output in metres // Input in degrees, Output in metres
static inline double distanceEarthD(double fromLatitude, static inline double distanceEarthD(double fromLatitude,
double fromLongitude, double fromLongitude,
double toLatitude, double toLatitude,
double toLongitude) double toLongitude)
{ {
double lat1r, lon1r, lat2r, lon2r, u, v; double lat1r, lon1r, lat2r, lon2r, u, v;
lat1r = toRadians(fromLatitude); lat1r = toRadians(fromLatitude);
lon1r = toRadians(fromLongitude); lon1r = toRadians(fromLongitude);
lat2r = toRadians(toLatitude); lat2r = toRadians(toLatitude);
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
static inline double distanceEarthP(point from, point to) static inline double distanceEarthP(point from, point to)
{ {
double lat1r, lon1r, lat2r, lon2r, u, v; double lat1r, lon1r, lat2r, lon2r, u, v;
lat1r = toRadians(from.latitude); lat1r = toRadians(from.latitude);
lon1r = toRadians(from.longitude); lon1r = toRadians(from.longitude);
lat2r = toRadians(to.latitude); lat2r = toRadians(to.latitude);
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
static inline struct point calculatePointDD(struct point coordinates, static inline struct point calculatePointDD(struct point coordinates,
double bearing, double bearing,
double distance) double distance)
{ {
double r_latitude = toRadians(coordinates.latitude); double r_latitude = toRadians(coordinates.latitude);
double r_longitude = toRadians(coordinates.longitude); double r_longitude = toRadians(coordinates.longitude);
double r_bearing = toRadians(bearing); double r_bearing = toRadians(bearing);
double newLatitude = double newLatitude =
std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) + std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) +
std::cos(r_latitude) * std::sin(distance / EARTH_M) * std::cos(r_latitude) * std::sin(distance / EARTH_M) *
std::cos(r_bearing)); std::cos(r_bearing));
double newLongitude = double newLongitude =
r_longitude + r_longitude +
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) * std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
std::cos(r_latitude), std::cos(r_latitude),
std::cos(distance / EARTH_M) - std::cos(distance / EARTH_M) -
std::sin(r_latitude) * std::sin(newLatitude)); std::sin(r_latitude) * std::sin(newLatitude));
return {toDegrees(newLatitude), toDegrees(newLongitude)}; return {toDegrees(newLatitude), toDegrees(newLongitude)};
} }
// Input in degrees, Output in radians // Input in degrees, Output in radians
static inline struct point calculatePointDR(struct point coordinates, static inline struct point calculatePointDR(struct point coordinates,
double bearing, double bearing,
double distance) double distance)
{ {
double r_latitude = toRadians(coordinates.latitude); double r_latitude = toRadians(coordinates.latitude);
double r_longitude = toRadians(coordinates.longitude); double r_longitude = toRadians(coordinates.longitude);
double r_bearing = toRadians(bearing); double r_bearing = toRadians(bearing);
double newLatitude = double newLatitude =
std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) + std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) +
std::cos(r_latitude) * std::sin(distance / EARTH_M) * std::cos(r_latitude) * std::sin(distance / EARTH_M) *
std::cos(r_bearing)); std::cos(r_bearing));
double newLongitude = double newLongitude =
r_longitude + r_longitude +
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) * std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
std::cos(r_latitude), std::cos(r_latitude),
std::cos(distance / EARTH_M) - std::cos(distance / EARTH_M) -
std::sin(r_latitude) * std::sin(newLatitude)); std::sin(r_latitude) * std::sin(newLatitude));
return {newLatitude, newLongitude}; return {newLatitude, newLongitude};
} }
// LAT/LON in radians, BEARING/Output in degrees // LAT/LON in radians, BEARING/Output in degrees
static inline struct point calculatePointRD(struct point coordinates, static inline struct point calculatePointRD(struct point coordinates,
double bearing, double bearing,
double distance) double distance)
{ {
double r_bearing = toRadians(bearing); double r_bearing = toRadians(bearing);
double newLatitude = std::asin( double newLatitude = std::asin(
std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) + std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) +
std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) * std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) *
std::cos(r_bearing)); std::cos(r_bearing));
double newLongitude = double newLongitude =
coordinates.longitude + coordinates.longitude +
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)};
} }
// LAT/LON/Output in radians, BEARING in degrees // LAT/LON/Output in radians, BEARING in degrees
static inline struct point calculatePointRR(struct point coordinates, static inline struct point calculatePointRR(struct point coordinates,
double bearing, double bearing,
double distance) double distance)
{ {
double r_bearing = toRadians(bearing); double r_bearing = toRadians(bearing);
double newLatitude = std::asin( double newLatitude = std::asin(
std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) + std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) +
std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) * std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) *
std::cos(r_bearing)); std::cos(r_bearing));
double newLongitude = double newLongitude =
coordinates.longitude + coordinates.longitude +
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};
} }
// Input in degrees, calculate from center // Input in degrees, calculate from center
static inline box calculateBoxDD(struct point center, static inline box calculateBoxDD(struct point center,
double bearing, double bearing,
double length, double length,
double width) double width)
{ {
struct point primaryCenter = calculatePointDR(center, bearing, -length / 2); struct point primaryCenter =
struct point secondaryCenter = calculatePointDR(center, bearing, -length / 2);
calculatePointDR(center, bearing, length / 2); struct point secondaryCenter =
double offsetHeadingNorth = calculatePointDR(center, bearing, length / 2);
bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360; double offsetHeadingNorth =
struct point primaryTop = bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360;
calculatePointRD(primaryCenter, offsetHeadingNorth, width / 2); struct point primaryTop =
struct point primaryBottom = calculatePointRD(primaryCenter, offsetHeadingNorth, width / 2);
calculatePointRD(primaryCenter, offsetHeadingNorth, -width / 2); struct point primaryBottom =
struct point secondaryTop = calculatePointRD(primaryCenter, offsetHeadingNorth, -width / 2);
calculatePointRD(secondaryCenter, offsetHeadingNorth, width / 2); struct point secondaryTop =
struct point secondaryBottom = calculatePointRD(secondaryCenter, offsetHeadingNorth, width / 2);
calculatePointRD(secondaryCenter, offsetHeadingNorth, -width / 2); struct point secondaryBottom =
calculatePointRD(secondaryCenter, offsetHeadingNorth, -width / 2);
return {primaryTop, secondaryTop, secondaryBottom, primaryBottom}; return {primaryTop, secondaryTop, secondaryBottom, primaryBottom};
} }
// Input in degrees, calculate from start end // Input in degrees, calculate from start end
static inline box calculateBoxDD(struct point start, static inline box calculateBoxDD(struct point start,
struct point end, struct point end,
double bearing, double bearing,
double width) double width)
{ {
double offsetHeadingNorth = double offsetHeadingNorth =
bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360; bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360;
struct point primaryTop = struct point primaryTop =
calculatePointDD(start, offsetHeadingNorth, width / 2); calculatePointDD(start, offsetHeadingNorth, width / 2);
struct point primaryBottom = struct point primaryBottom =
calculatePointDD(start, offsetHeadingNorth, -width / 2); calculatePointDD(start, offsetHeadingNorth, -width / 2);
struct point secondaryTop = struct point secondaryTop =
calculatePointDD(end, offsetHeadingNorth, width / 2); calculatePointDD(end, offsetHeadingNorth, width / 2);
struct point secondaryBottom = struct point secondaryBottom =
calculatePointDD(end, offsetHeadingNorth, -width / 2); calculatePointDD(end, offsetHeadingNorth, -width / 2);
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
+54 -34
View File
@@ -1,51 +1,71 @@
#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 websocket namespace gaconnector
{ {
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 */
/* Structures and enums */ /* Structures and enums */
struct data { struct data {
std::int32_t pause = 0; std::int32_t pause = 0;
float pBrake = 0; float pBrake = 0;
std::int32_t onGrnd = 0; std::int32_t onGrnd = 0;
float totFuelKg = 0; float totFuelKg = 0;
float truHdg = 0; float truHdg = 0;
double alt = 0; double alt = 0;
float gs = 0; float gs = 0;
float ias = 0; float ias = 0;
float vs = 0; float vs = 0;
double lat = 0; double lat = 0;
double lon = 0; double lon = 0;
float ff[8] = {0, 0, 0, 0, 0, 0, 0, 0}; float ff[8] = {0, 0, 0, 0, 0, 0, 0, 0};
float maxSpd = 0; float maxSpd = 0;
char path[513] = ""; char path[513] = "";
float uptime = 0; float uptime = 0;
float magHeading = 0; float magHeading = 0;
float payloadKg = 0; float payloadKg = 0;
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;
}; };
struct command_port { struct command_port {
double latitude; double latitude;
double longitude; double longitude;
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
+27 -20
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
@@ -20,27 +20,34 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace websocket namespace gaconnector
{ {
class Websocket namespace websocket
{ {
private: class Websocket
char lastPath[513] = ""; {
char lastHash[2 * MD5LEN + 1] = ""; private:
ix::WebSocket *webSocket = nullptr; bool isLoggedIn = false;
std::string host; enum failures failureMode = failures::NONE;
std::string user; char lastPath[513] = "";
std::function<void(const std::string)> toLog; char lastHash[2 * MD5LEN + 1] = "";
ix::WebSocket *webSocket = nullptr;
std::string host;
std::string user;
std::string token;
std::function<void(const std::string)> toLog;
public: public:
Websocket(std::string host, Websocket(std::string host,
std::string user, std::string user,
std::function<void(const std::string)> toLog); std::string token,
~Websocket(); std::function<void(const std::string)> toLog);
void onClientMessageCallback(const ix::WebSocketMessagePtr &msg); ~Websocket();
void sendData(data &d); void onClientMessageCallback(const ix::WebSocketMessagePtr &msg);
}; void sendData(data &d);
} // namespace websocket };
} // namespace websocket
} // namespace gaconnector
} // namespace germanairlinesva } // namespace germanairlinesva
#endif #endif
+111 -88
View File
@@ -2,113 +2,136 @@
namespace germanairlinesva namespace germanairlinesva
{ {
namespace websocket namespace gaconnector
{ {
Websocket::Websocket(std::string host, namespace websocket
std::string user,
std::function<void(const std::string)> toLog)
: host(host), user(user), toLog(std::move(toLog))
{ {
Websocket::Websocket(std::string host,
std::string user,
std::string token,
std::function<void(const std::string)> toLog)
: host(host), user(user), token(token), toLog(std::move(toLog))
{
#ifdef IBM #ifdef IBM
// Required on Windows // Required on Windows
ix::initNetSystem(); ix::initNetSystem();
#endif #endif
this->webSocket = new ix::WebSocket(); this->webSocket = new ix::WebSocket();
this->webSocket->enableAutomaticReconnection(); this->webSocket->setExtraHeaders({
this->webSocket->setUrl(host); {"origin", "GAClient"},
this->webSocket->setOnMessageCallback( {"authentication", "Bearer " + this->token},
[this](const ix::WebSocketMessagePtr &msg) { {"user", this->user},
this->onClientMessageCallback(msg); });
}); this->webSocket->enableAutomaticReconnection();
this->webSocket->start(); this->webSocket->setUrl(host);
} this->webSocket->setOnMessageCallback(
[this](const ix::WebSocketMessagePtr &msg) {
this->onClientMessageCallback(msg);
});
this->webSocket->start();
}
Websocket::~Websocket() Websocket::~Websocket()
{ {
this->webSocket->stop(); this->webSocket->stop();
this->toLog("WebSocket stopped"); this->toLog("WebSocket stopped");
#ifdef IBM #ifdef IBM
// Required on Windows // Required on Windows
ix::uninitNetSystem(); ix::uninitNetSystem();
#endif #endif
} }
void Websocket::onClientMessageCallback(const ix::WebSocketMessagePtr &msg) void Websocket::onClientMessageCallback(const ix::WebSocketMessagePtr &msg)
{ {
if (msg->type == ix::WebSocketMessageType::Open) { if (msg->type == ix::WebSocketMessageType::Open) {
std::stringstream debug_msg;
debug_msg << std::endl << "New connection" << std::endl;
debug_msg << "Uri: " << msg->openInfo.uri << std::endl;
debug_msg << "Headers:" << std::endl;
for (const auto &it : msg->openInfo.headers) {
debug_msg << it.first << ": " << it.second << std::endl;
}
this->toLog(debug_msg.str());
this->webSocket->send("MASTER:" + user);
this->toLog("Connecting as " + user);
} 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 << "New connection" << std::endl;
debug_msg << "Code: " << msg->closeInfo.code << std::endl; debug_msg << "\tUri: " << msg->openInfo.uri << std::endl;
debug_msg << "Reason: " << msg->closeInfo.reason << std::endl; debug_msg << "\tHeaders:" << std::endl;
debug_msg << "Remote: " << msg->closeInfo.remote << std::endl; for (const auto &it : msg->openInfo.headers) {
debug_msg << "\t\t" << it.first << ": " << it.second << std::endl;
}
this->toLog(debug_msg.str());
this->toLog("Connected as " + user);
this->isLoggedIn = true;
this->failureMode = failures::NONE;
} else if (msg->type == ix::WebSocketMessageType::Close) {
std::stringstream debug_msg;
debug_msg << "Connection closed" << std::endl;
debug_msg << "\tCode: " << msg->closeInfo.code << std::endl;
debug_msg << "\tReason: " << msg->closeInfo.reason << 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;
this->toLog(debug_msg.str()); if (msg->errorInfo.http_status == 401) {
} else if (msg->type == ix::WebSocketMessageType::Message) { this->webSocket->disableAutomaticReconnection();
if (!msg->str.empty()) {
this->toLog(msg->str);
}
}
}
void Websocket::sendData(data &d) this->toLog("Disabling automatic reconnection due to auth failure");
{ this->failureMode = failures::AUTH;
if (strcmp(d.path, this->lastPath) != 0) { } else if (msg->errorInfo.http_status == 500 &&
strcpy(this->lastPath, d.path); msg->errorInfo.reason.find("Duplicate") !=
if (util::generateMD5(d.path, this->lastHash, this->toLog)) { std::string::npos) {
strcpy(this->lastHash, "NOT SET"); 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->isLoggedIn = false;
} else if (msg->type == ix::WebSocketMessageType::Message) {
if (!msg->str.empty()) {
this->toLog(msg->str);
}
} }
} }
nlohmann::json json = { void Websocket::sendData(data &d)
{"altitude", d.alt}, {
{"vs", d.vs}, if (strcmp(d.path, this->lastPath) != 0) {
{"ias", d.ias}, strcpy(this->lastPath, d.path);
{"magHdg", d.magHeading}, if (utilities::generateMD5(d.path, this->lastHash, this->toLog)) {
{"truHdg", d.truHdg}, strcpy(this->lastHash, "NO HASH");
{"totFuel", d.totFuelKg}, }
{"fuelFlow", d.ff}, }
{"hash", this->lastHash},
};
if (this->webSocket != nullptr) { nlohmann::json json = {
std::ostringstream msg; {"altitude", d.alt},
msg << "SEND:" << user << ":" << json.dump(); {"vs", d.vs},
this->webSocket->send(msg.str(), false); {"ias", d.ias},
{"magHdg", d.magHeading},
{"truHdg", d.truHdg},
{"totFuel", d.totFuelKg},
{"fuelFlow", d.ff},
{"path", d.path},
{"hash", this->lastHash},
};
if (this->webSocket != nullptr) {
std::ostringstream msg;
msg << "SEND:" << user << ":" << json.dump();
this->webSocket->send(msg.str(), false);
}
} }
} } // 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"
+16 -165
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>( toLog);
"wss://ws.hofmannnet.myhome-server.de:8000",
configuration->getUser(),
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);