Compare commits
7 Commits
42acea35bb
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 5af921f4cc | |||
| 176c43d5a6 | |||
| c214d473e2 | |||
| 3a9db68e74 | |||
| 0a150391b8 | |||
| 396aa8d807 | |||
| eafe0b18f6 |
@@ -15,4 +15,10 @@
|
|||||||
- path: Path to ACF/AIR/Whatever on MSFS
|
- path: Path to ACF/AIR/Whatever on MSFS
|
||||||
- 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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 "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) &&
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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(©, &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(©, &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
|
||||||
@@ -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
@@ -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
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
@@ -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
@@ -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
@@ -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(©, &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(©, &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);
|
||||||
|
|||||||
Reference in New Issue
Block a user