Commit with fixed paths
This commit is contained in:
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.{c,h,cpp,hpp}]
|
||||
indent_size = 4
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Even Rognlien
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
285
README.md
285
README.md
@@ -1 +1,284 @@
|
||||
node-simconnect
|
||||
# node-simconnect :airplane:
|
||||
Wrapper for the SimConnect SDK for Flight Simulator X and Prepar3D (Windows only)
|
||||
|
||||
This project is at a very early stage and wraps only a few basic SimConnect function calls. Feel free to join the development! :)
|
||||
|
||||
# Installation 📦
|
||||
|
||||
node-simconnect is a native NodeJS addon written in C++ and must be compiled to a dynamic C++ library before it can be loaded as a module in NodeJS. Included in this repository is a prebuilt binary built with SimConnect 10.0.61259.0 (FSX SP2), which is compatible with FSX SP2, FSX:SE and all versions of Prepar3D. Because SimConnect 10.0.61259.0 is a 32 bit library, you must use the 32 bit version of NodeJS in order to import the module.
|
||||
|
||||
To install node-simconnect using the included binary:
|
||||
|
||||
`npm install node-simconnect`
|
||||
|
||||
**Note: The included binary requires the 32 bit version of NodeJS.**
|
||||
|
||||
# Usage :grey_question:
|
||||
Import the module and create an instance:
|
||||
|
||||
```ts
|
||||
const { SimConnect } = require('node-simconnect');
|
||||
|
||||
const simConnect = new SimConnect();
|
||||
```
|
||||
|
||||
## <a name="open"></a>open
|
||||
|
||||
Attempts to opens a session with SimConnect. If it fails to connect (eg. if sim is not running), the function immediately returns `false`. The success callback function will provide the `Client` object which you will use to interact with the simulator. The available features are described below. Please refer to [example.js](examples/nodejs/example.js) for more help.
|
||||
|
||||
```ts
|
||||
open(
|
||||
appName: string,
|
||||
onSuccess: (client: Client) => void,
|
||||
onQuit: () => void,
|
||||
onException: (details) => void,
|
||||
onError: (details) => void
|
||||
) : boolean;
|
||||
```
|
||||
|
||||
```ts
|
||||
const ok = simConnect.open(
|
||||
"My app's name",
|
||||
successCallback,
|
||||
quitCallback,
|
||||
exceptionCallback,
|
||||
errorCallback
|
||||
);
|
||||
|
||||
if (!ok) {
|
||||
console.log('Failed to connect. Please try again.');
|
||||
}
|
||||
|
||||
function successCallback(client) {
|
||||
const { name, version } = client;
|
||||
console.log(`Connected to: ${name}\nSimConnect version: ${version}`);
|
||||
// ... do stuff with client
|
||||
}
|
||||
|
||||
function quitCallback() {
|
||||
console.log('Sim quit');
|
||||
}
|
||||
|
||||
function exceptionCallback(details) {
|
||||
const { name, dwException, dwSendID, dwIndex } = details;
|
||||
console.log(`The following exception occured: ${name}`);
|
||||
}
|
||||
|
||||
function errorCallback(details) {
|
||||
const { message, NTSTATUS } = details;
|
||||
console.log(`The following error occured: ${message}`);
|
||||
}
|
||||
```
|
||||
|
||||
## <a name="requestDataOnSimObject"></a>requestDataOnSimObject
|
||||
|
||||
Request one or more [Simulation Variables](https://msdn.microsoft.com/en-us/library/cc526981.aspx) and set a callback function to later handle the received data. See [SDK Reference](https://msdn.microsoft.com/en-us/library/cc526983.aspx#SimConnect_RequestDataOnSimObject) for more details.
|
||||
|
||||
Each simulation variable is defined by an array.
|
||||
|
||||
Definition:
|
||||
```ts
|
||||
requestDataOnSimObject(
|
||||
requestedValues: any[][] | number,
|
||||
options: {
|
||||
period: PERIOD, // SIMCONNECT_PERIOD_...
|
||||
objectId: OBJECT_ID, // SIMCONNECT_OBJECT_...
|
||||
flags: DATA_REQUEST_FLAG, // SIMCONNECT_DATA_REQUEST_FLAG_...
|
||||
},
|
||||
callback: (data: any) => void
|
||||
) : void
|
||||
```
|
||||
Requested value example:
|
||||
```ts
|
||||
[
|
||||
"Plane Latitude", // Datum name
|
||||
"degrees", // Units name
|
||||
DATA_TYPE.FLOAT64, // Datum type (optional, FLOAT64 is default and works for most data types)
|
||||
0 // Epsilon (optional, 0 is default)
|
||||
]
|
||||
```
|
||||
Full example:
|
||||
```ts
|
||||
client.requestDataOnSimObject([
|
||||
["Plane Latitude", "degrees"],
|
||||
["Plane Longitude", "degrees"],
|
||||
["PLANE ALTITUDE", "feet"]
|
||||
], {
|
||||
period: PERIOD.SIM_FRAME, // SIMCONNECT_PERIOD_ONCE
|
||||
objectId: OBJECT_ID.USER, // SIMCONNECT_OBJECT_ID_USER
|
||||
flags: DATA_REQUEST_FLAG.CHANGED, // SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT
|
||||
}, (data) => {
|
||||
console.log(
|
||||
"Latitude: " + data["Plane Latitude"] + "\n" +
|
||||
"Longitude: " + data["Plane Longitude"] + "\n" +
|
||||
"Altitude: " + data["PLANE ALTITUDE"] + " feet"
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## <a name="requestDataOnSimObjectType"></a>requestDataOnSimObjectType
|
||||
Similar to `requestDataOnSimObject`. Used to retrieve information about simulation objects of a given type that are within a specified radius of the user's aircraft. See [SDK Reference](https://msdn.microsoft.com/en-us/library/cc526983.aspx#SimConnect_RequestDataOnSimObjectType) for more details.
|
||||
|
||||
Definition:
|
||||
```ts
|
||||
requestDataOnSimObjectType(
|
||||
requestedValues: any[][] | number,
|
||||
options: {
|
||||
radius: number,
|
||||
type: SIMOBJECT_TYPE, // SIMCONNECT_SIMOBJECT_TYPE_...
|
||||
},
|
||||
callback: (data: any) => void
|
||||
) : void
|
||||
```
|
||||
Example: This will receive info about all aircraft within a 10 km radius. The callback will run one time for each identified aircraft. Notice that when `STRINGV` is requested, the unit should be `null`
|
||||
```ts
|
||||
client.requestDataOnSimObjectType([
|
||||
["ATC MODEL", null, 11], // SIMCONNECT_DATATYPE_STRINGV
|
||||
["Plane Latitude", "degrees"],
|
||||
["Plane Longitude", "degrees"]
|
||||
], {
|
||||
radius: 10000,
|
||||
type: SIMOBJECT_TYPE.AIRCRAFT
|
||||
}, (data) => {
|
||||
// Called for each aircraft
|
||||
console.log(data);
|
||||
});
|
||||
```
|
||||
|
||||
## <a name="createDataDefinition"></a>createDataDefinition
|
||||
Used to create a data definition. Returns an id which can be used with `requestDataOnSimObject`/`requestDataOnSimObjectType` in place of the 2D array. This should be used when you have multiple requests for the same data - otherwise the app will crash after receiving too many requests. Example:
|
||||
|
||||
```ts
|
||||
createDataDefinition(requestedValues: any[][]) : number
|
||||
```
|
||||
|
||||
```ts
|
||||
var navInfoDefId = client.createDataDefinition([
|
||||
["NAV DME:1", "Nautical miles"],
|
||||
["NAV GLIDE SLOPE ERROR:1", "Degrees"],
|
||||
["NAV RADIAL ERROR:1", "Degrees"],
|
||||
]);
|
||||
|
||||
setInterval(() => {
|
||||
client.requestDataOnSimObjectType(
|
||||
navInfoDefId,
|
||||
{
|
||||
radius: 0,
|
||||
type: SIMOBJECT_TYPE.USER, // SIMCONNECT_SIMOBJECT_TYPE_...
|
||||
},
|
||||
(data) => {
|
||||
console.log(data)
|
||||
}
|
||||
);
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
## <a name="setDataOnSimObject"></a>setDataOnSimObject
|
||||
Set a single [Simulation Variable](https://msdn.microsoft.com/en-us/library/cc526981.aspx) on user aircraft. First parameter is the datum name, second is the units name and last is the value.
|
||||
|
||||
Definition:
|
||||
```ts
|
||||
setDataOnSimObject(
|
||||
variableName: string,
|
||||
unit: string,
|
||||
value: number
|
||||
) : void
|
||||
```
|
||||
|
||||
Example:
|
||||
```ts
|
||||
client.setDataOnSimObject("GENERAL ENG THROTTLE LEVER POSITION:1", "Percent", 50);
|
||||
```
|
||||
|
||||
## <a name="subscribeToSystemEvent"></a>subscribeToSystemEvent
|
||||
Subscribe to a system event. See [SDK Reference](https://msdn.microsoft.com/en-us/library/cc526983.aspx#SimConnect_SubscribeToSystemEvent) for available events.
|
||||
|
||||
```ts
|
||||
subscribeToSystemEvent(
|
||||
eventName: string,
|
||||
callback: (value: number) => void
|
||||
) : void
|
||||
```
|
||||
|
||||
Example:
|
||||
```ts
|
||||
client.subscribeToSystemEvent("Pause", (paused) => {
|
||||
// Called when the system event occurs
|
||||
console.log(paused ? "Sim paused" : "Sim un-paused");
|
||||
});
|
||||
```
|
||||
|
||||
## <a name="close"></a>close
|
||||
Manually close the connection to SimConnect. Returns `false` if it fails.
|
||||
|
||||
```ts
|
||||
close() : boolean
|
||||
```
|
||||
|
||||
Example:
|
||||
```ts
|
||||
const success = client.close();
|
||||
```
|
||||
|
||||
# Manual build 🔨
|
||||
You might wish to build node-simconnect manually (eg. with the 64-bit SimConnect SDK that comes with Prepar3D v4). Due to the licensing of the SimConnect SDK the library files are not included in this repository, so you must provide these yourself.
|
||||
|
||||
## Requirements
|
||||
* FSX or P3D SimConnect SDK files (.lib and .h).
|
||||
* Node.js (32 or 64 bit depending on which SDK you are using. FSX is 32 bit)
|
||||
* Python and MSVS 2017 build tools or newer. Check out [windows-build-tools](https://www.npmjs.com/package/windows-build-tools).
|
||||
|
||||
|
||||
## Build
|
||||
You must provide your own copy of the SDK files. By default these can be found here:
|
||||
|
||||
* Microsoft Flight Simulator ("2020")
|
||||
* `MSFS SDK/SimConnect SDK/include/SimConnect.h`
|
||||
* `MSFS SDK/SimConnect SDK/lib/static/SimConnect.lib`
|
||||
* FSX Steam Edition
|
||||
* `FSX/SDK/Core Utilities Kit/SimConnect SDK/inc/SimConnect.h`
|
||||
* `FSX/SDK/Core Utilities Kit/SimConnect SDK/lib/SimConnect.lib`
|
||||
|
||||
Once you have located the SDK files
|
||||
|
||||
1. Navigate to `[your project]/node-modules/node-simconnect`
|
||||
1. Create a folder named `SimConnect` and copy the two folders `inc` and `lib` from the SimConnect SDK installation over to the new directory. These should include `SimConnect.h` and `SimConnect.lib`, respectively.
|
||||
1. Open a terminal in `[your project]/node-modules/node-simconnect` and run `npm run rebuild`.
|
||||
1. Verify that the build is working by running the example program: `node examples/nodejs/example.js`.
|
||||
|
||||
**Note:** Your app will attempt to load the binary file in the following order:
|
||||
1. `build/Release`
|
||||
1. `build/Debug`
|
||||
1. `bin/win_ia32` (included pre build)
|
||||
|
||||
# Using node-simconnect with Electron or NW.JS :electron:
|
||||
To use `node-simconnect` with Electron or NW.JS, the package must be built specifically for those frameworks. Read more about using native addons here: [Electron](https://github.com/electron/electron/blob/master/docs/tutorial/using-native-node-modules.md), [NW.JS](http://docs.nwjs.io/en/latest/For%20Users/Advanced/Use%20Native%20Node%20Modules/)
|
||||
|
||||
## To build native Electron (version 11 or newer) addon:
|
||||
|
||||
```HOME=~/.electron-gyp node-gyp rebuild --target=11.0.0 --arch=ia32 --msvs_version=2017 --dist-url=https://electronjs.org/headers```
|
||||
|
||||
(where `--target` is the version of Electron and `--arch` is either `ia32` or `x64`).
|
||||
|
||||
## To build native NW.JS addon:
|
||||
|
||||
```nw-gyp rebuild --target=0.49.1 --arch=ia32 --msvs_version=2017```
|
||||
|
||||
(where `--target` is the version of NW.JS).
|
||||
|
||||
# Development
|
||||
|
||||
1. Install [Microsoft Visual Studio 2019](https://visualstudio.microsoft.com/) (Community Edition is sufficient)
|
||||
1. Run `npm run rebuild:dev`
|
||||
1. Open `build\binding.sln`
|
||||
|
||||
### Debugging with Microsoft Visual Studio
|
||||
|
||||
1. In the Solution Explorer right click on **node_simconnect** and select **Properties**
|
||||
1. Select **Configuration: Debug**
|
||||
1. Open the **Debugging** page and set the following properties:
|
||||
* **Command**: `$(ProgramFiles)\nodejs\node.exe`
|
||||
* **Command Arguments**: `$(ProjectDir)..\examples\nodejs\example.js`
|
||||
|
||||
## Licence
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
BIN
bin/win32-x64-99/node-simconnect.node
Normal file
BIN
bin/win32-x64-99/node-simconnect.node
Normal file
Binary file not shown.
BIN
bin/win_ia32/node_simconnect.node
Normal file
BIN
bin/win_ia32/node_simconnect.node
Normal file
Binary file not shown.
52
binding.gyp
Normal file
52
binding.gyp
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "node_simconnect",
|
||||
"sources": [
|
||||
"src/simconnect_session.cc",
|
||||
"src/simconnect_session.h",
|
||||
"src/commons.h",
|
||||
"src/binding.h",
|
||||
"src/binding.cc",
|
||||
"src/client_handler.h",
|
||||
"src/client_handler.cc",
|
||||
"src/dispatch_queue_worker.h",
|
||||
"src/dispatch_queue_worker.cc",
|
||||
],
|
||||
'include_dirs': [
|
||||
"SimConnect/Inc",
|
||||
"<!(node -p \"require('node-addon-api').include_dir\")",
|
||||
],
|
||||
"link_settings": {
|
||||
"libraries": [
|
||||
"../SimConnect/lib/SimConnect",
|
||||
"Ws2_32.lib",
|
||||
"Shlwapi.lib"
|
||||
]
|
||||
},
|
||||
'cflags!': [ '-fno-exceptions' ],
|
||||
'cflags_cc!': [ '-fno-exceptions' ],
|
||||
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': '3', # /MDd
|
||||
'ExceptionHandling': 1,
|
||||
'AdditionalOptions': [ '-std:c++17', ],
|
||||
}
|
||||
}
|
||||
},
|
||||
'Release': {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': '2', # /MD
|
||||
'ExceptionHandling': 1,
|
||||
'AdditionalOptions': [ '-std:c++17', ],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
build/.vs/binding/v17/.suo
Normal file
BIN
build/.vs/binding/v17/.suo
Normal file
Binary file not shown.
BIN
build/.vs/binding/v17/Browse.VC.db
Normal file
BIN
build/.vs/binding/v17/Browse.VC.db
Normal file
Binary file not shown.
1
build/Release/.forge-meta
Normal file
1
build/Release/.forge-meta
Normal file
@@ -0,0 +1 @@
|
||||
x64--99
|
||||
BIN
build/Release/SimConnect.dll
Normal file
BIN
build/Release/SimConnect.dll
Normal file
Binary file not shown.
BIN
build/Release/node_simconnect.exp
Normal file
BIN
build/Release/node_simconnect.exp
Normal file
Binary file not shown.
BIN
build/Release/node_simconnect.ilk
Normal file
BIN
build/Release/node_simconnect.ilk
Normal file
Binary file not shown.
BIN
build/Release/node_simconnect.lib
Normal file
BIN
build/Release/node_simconnect.lib
Normal file
Binary file not shown.
BIN
build/Release/node_simconnect.node
Normal file
BIN
build/Release/node_simconnect.node
Normal file
Binary file not shown.
BIN
build/Release/node_simconnect.pdb
Normal file
BIN
build/Release/node_simconnect.pdb
Normal file
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<ProjectOutputs>
|
||||
<ProjectOutput>
|
||||
<FullPath>D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-simconnect\build\Release\node_simconnect.node</FullPath>
|
||||
</ProjectOutput>
|
||||
</ProjectOutputs>
|
||||
<ContentFiles />
|
||||
<SatelliteDlls />
|
||||
<NonRecipeFileRefs />
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.30.30705:TargetPlatformVersion=10.0.19041.0:
|
||||
Release|x64|D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-simconnect\build\|
|
||||
Binary file not shown.
BIN
build/Release/obj/node_simconnect/src/binding.obj
Normal file
BIN
build/Release/obj/node_simconnect/src/binding.obj
Normal file
Binary file not shown.
BIN
build/Release/obj/node_simconnect/src/client_handler.obj
Normal file
BIN
build/Release/obj/node_simconnect/src/client_handler.obj
Normal file
Binary file not shown.
BIN
build/Release/obj/node_simconnect/src/dispatch_queue_worker.obj
Normal file
BIN
build/Release/obj/node_simconnect/src/dispatch_queue_worker.obj
Normal file
Binary file not shown.
BIN
build/Release/obj/node_simconnect/src/simconnect_session.obj
Normal file
BIN
build/Release/obj/node_simconnect/src/simconnect_session.obj
Normal file
Binary file not shown.
BIN
build/Release/obj/node_simconnect/win_delay_load_hook.obj
Normal file
BIN
build/Release/obj/node_simconnect/win_delay_load_hook.obj
Normal file
Binary file not shown.
19
build/binding.sln
Normal file
19
build/binding.sln
Normal file
@@ -0,0 +1,19 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2015
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "node_simconnect", "node_simconnect.vcxproj", "{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Release|x64 = Release|x64
|
||||
Debug|x64 = Debug|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}.Release|x64.ActiveCfg = Release|x64
|
||||
{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}.Release|x64.Build.0 = Release|x64
|
||||
{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}.Debug|x64.Build.0 = Debug|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
355
build/config.gypi
Normal file
355
build/config.gypi
Normal file
@@ -0,0 +1,355 @@
|
||||
# Do not edit. File was generated by node-gyp's "configure" step
|
||||
{
|
||||
"target_defaults": {
|
||||
"cflags": [],
|
||||
"default_configuration": "Release",
|
||||
"defines": [],
|
||||
"include_dirs": [],
|
||||
"libraries": [],
|
||||
"msbuild_toolset": "v143",
|
||||
"msvs_windows_target_platform_version": "10.0.19041.0"
|
||||
},
|
||||
"variables": {
|
||||
"asan": 0,
|
||||
"build_v8_with_gn": "false",
|
||||
"built_with_electron": 1,
|
||||
"coverage": "false",
|
||||
"dcheck_always_on": 0,
|
||||
"debug_nghttp2": "false",
|
||||
"debug_node": "false",
|
||||
"enable_lto": "false",
|
||||
"enable_pgo_generate": "false",
|
||||
"enable_pgo_use": "false",
|
||||
"error_on_warn": "false",
|
||||
"force_dynamic_crt": 0,
|
||||
"host_arch": "x64",
|
||||
"icu_data_in": "..\\..\\deps\\icu-tmp\\icudt69l.dat",
|
||||
"icu_endianness": "l",
|
||||
"icu_gyp_path": "tools/icu/icu-generic.gyp",
|
||||
"icu_path": "deps/icu-small",
|
||||
"icu_small": "false",
|
||||
"icu_ver_major": "69",
|
||||
"is_debug": 0,
|
||||
"llvm_version": "0.0",
|
||||
"napi_build_version": "8",
|
||||
"node_byteorder": "little",
|
||||
"node_debug_lib": "false",
|
||||
"node_enable_d8": "false",
|
||||
"node_install_npm": "true",
|
||||
"node_library_files": [
|
||||
"lib/assert.js",
|
||||
"lib/async_hooks.js",
|
||||
"lib/buffer.js",
|
||||
"lib/child_process.js",
|
||||
"lib/cluster.js",
|
||||
"lib/console.js",
|
||||
"lib/constants.js",
|
||||
"lib/crypto.js",
|
||||
"lib/dgram.js",
|
||||
"lib/diagnostics_channel.js",
|
||||
"lib/dns.js",
|
||||
"lib/domain.js",
|
||||
"lib/events.js",
|
||||
"lib/fs.js",
|
||||
"lib/http.js",
|
||||
"lib/http2.js",
|
||||
"lib/https.js",
|
||||
"lib/inspector.js",
|
||||
"lib/module.js",
|
||||
"lib/net.js",
|
||||
"lib/os.js",
|
||||
"lib/path.js",
|
||||
"lib/perf_hooks.js",
|
||||
"lib/process.js",
|
||||
"lib/punycode.js",
|
||||
"lib/querystring.js",
|
||||
"lib/readline.js",
|
||||
"lib/repl.js",
|
||||
"lib/stream.js",
|
||||
"lib/string_decoder.js",
|
||||
"lib/sys.js",
|
||||
"lib/timers.js",
|
||||
"lib/tls.js",
|
||||
"lib/trace_events.js",
|
||||
"lib/tty.js",
|
||||
"lib/url.js",
|
||||
"lib/util.js",
|
||||
"lib/v8.js",
|
||||
"lib/vm.js",
|
||||
"lib/wasi.js",
|
||||
"lib/worker_threads.js",
|
||||
"lib/zlib.js",
|
||||
"lib/_http_agent.js",
|
||||
"lib/_http_client.js",
|
||||
"lib/_http_common.js",
|
||||
"lib/_http_incoming.js",
|
||||
"lib/_http_outgoing.js",
|
||||
"lib/_http_server.js",
|
||||
"lib/_stream_duplex.js",
|
||||
"lib/_stream_passthrough.js",
|
||||
"lib/_stream_readable.js",
|
||||
"lib/_stream_transform.js",
|
||||
"lib/_stream_wrap.js",
|
||||
"lib/_stream_writable.js",
|
||||
"lib/_tls_common.js",
|
||||
"lib/_tls_wrap.js",
|
||||
"lib/assert/strict.js",
|
||||
"lib/dns/promises.js",
|
||||
"lib/fs/promises.js",
|
||||
"lib/internal/abort_controller.js",
|
||||
"lib/internal/assert.js",
|
||||
"lib/internal/async_hooks.js",
|
||||
"lib/internal/blob.js",
|
||||
"lib/internal/blocklist.js",
|
||||
"lib/internal/buffer.js",
|
||||
"lib/internal/child_process.js",
|
||||
"lib/internal/cli_table.js",
|
||||
"lib/internal/constants.js",
|
||||
"lib/internal/dgram.js",
|
||||
"lib/internal/dtrace.js",
|
||||
"lib/internal/encoding.js",
|
||||
"lib/internal/errors.js",
|
||||
"lib/internal/error_serdes.js",
|
||||
"lib/internal/event_target.js",
|
||||
"lib/internal/fixed_queue.js",
|
||||
"lib/internal/freelist.js",
|
||||
"lib/internal/freeze_intrinsics.js",
|
||||
"lib/internal/heap_utils.js",
|
||||
"lib/internal/histogram.js",
|
||||
"lib/internal/http.js",
|
||||
"lib/internal/idna.js",
|
||||
"lib/internal/inspector_async_hook.js",
|
||||
"lib/internal/js_stream_socket.js",
|
||||
"lib/internal/linkedlist.js",
|
||||
"lib/internal/net.js",
|
||||
"lib/internal/options.js",
|
||||
"lib/internal/priority_queue.js",
|
||||
"lib/internal/querystring.js",
|
||||
"lib/internal/repl.js",
|
||||
"lib/internal/socketaddress.js",
|
||||
"lib/internal/socket_list.js",
|
||||
"lib/internal/stream_base_commons.js",
|
||||
"lib/internal/timers.js",
|
||||
"lib/internal/trace_events_async_hooks.js",
|
||||
"lib/internal/tty.js",
|
||||
"lib/internal/url.js",
|
||||
"lib/internal/util.js",
|
||||
"lib/internal/v8_prof_polyfill.js",
|
||||
"lib/internal/v8_prof_processor.js",
|
||||
"lib/internal/validators.js",
|
||||
"lib/internal/watchdog.js",
|
||||
"lib/internal/worker.js",
|
||||
"lib/internal/assert/assertion_error.js",
|
||||
"lib/internal/assert/calltracker.js",
|
||||
"lib/internal/bootstrap/environment.js",
|
||||
"lib/internal/bootstrap/loaders.js",
|
||||
"lib/internal/bootstrap/node.js",
|
||||
"lib/internal/bootstrap/pre_execution.js",
|
||||
"lib/internal/bootstrap/switches/does_not_own_process_state.js",
|
||||
"lib/internal/bootstrap/switches/does_own_process_state.js",
|
||||
"lib/internal/bootstrap/switches/is_main_thread.js",
|
||||
"lib/internal/bootstrap/switches/is_not_main_thread.js",
|
||||
"lib/internal/child_process/serialization.js",
|
||||
"lib/internal/cluster/child.js",
|
||||
"lib/internal/cluster/primary.js",
|
||||
"lib/internal/cluster/round_robin_handle.js",
|
||||
"lib/internal/cluster/shared_handle.js",
|
||||
"lib/internal/cluster/utils.js",
|
||||
"lib/internal/cluster/worker.js",
|
||||
"lib/internal/console/constructor.js",
|
||||
"lib/internal/console/global.js",
|
||||
"lib/internal/crypto/aes.js",
|
||||
"lib/internal/crypto/certificate.js",
|
||||
"lib/internal/crypto/cipher.js",
|
||||
"lib/internal/crypto/diffiehellman.js",
|
||||
"lib/internal/crypto/dsa.js",
|
||||
"lib/internal/crypto/ec.js",
|
||||
"lib/internal/crypto/hash.js",
|
||||
"lib/internal/crypto/hashnames.js",
|
||||
"lib/internal/crypto/hkdf.js",
|
||||
"lib/internal/crypto/keygen.js",
|
||||
"lib/internal/crypto/keys.js",
|
||||
"lib/internal/crypto/mac.js",
|
||||
"lib/internal/crypto/pbkdf2.js",
|
||||
"lib/internal/crypto/random.js",
|
||||
"lib/internal/crypto/rsa.js",
|
||||
"lib/internal/crypto/scrypt.js",
|
||||
"lib/internal/crypto/sig.js",
|
||||
"lib/internal/crypto/util.js",
|
||||
"lib/internal/crypto/webcrypto.js",
|
||||
"lib/internal/crypto/x509.js",
|
||||
"lib/internal/debugger/inspect.js",
|
||||
"lib/internal/debugger/inspect_client.js",
|
||||
"lib/internal/debugger/inspect_repl.js",
|
||||
"lib/internal/dns/promises.js",
|
||||
"lib/internal/dns/utils.js",
|
||||
"lib/internal/fs/dir.js",
|
||||
"lib/internal/fs/promises.js",
|
||||
"lib/internal/fs/read_file_context.js",
|
||||
"lib/internal/fs/rimraf.js",
|
||||
"lib/internal/fs/streams.js",
|
||||
"lib/internal/fs/sync_write_stream.js",
|
||||
"lib/internal/fs/utils.js",
|
||||
"lib/internal/fs/watchers.js",
|
||||
"lib/internal/fs/cp/cp-sync.js",
|
||||
"lib/internal/fs/cp/cp.js",
|
||||
"lib/internal/http2/compat.js",
|
||||
"lib/internal/http2/core.js",
|
||||
"lib/internal/http2/util.js",
|
||||
"lib/internal/legacy/processbinding.js",
|
||||
"lib/internal/main/check_syntax.js",
|
||||
"lib/internal/main/eval_stdin.js",
|
||||
"lib/internal/main/eval_string.js",
|
||||
"lib/internal/main/inspect.js",
|
||||
"lib/internal/main/print_help.js",
|
||||
"lib/internal/main/prof_process.js",
|
||||
"lib/internal/main/repl.js",
|
||||
"lib/internal/main/run_main_module.js",
|
||||
"lib/internal/main/worker_thread.js",
|
||||
"lib/internal/modules/package_json_reader.js",
|
||||
"lib/internal/modules/run_main.js",
|
||||
"lib/internal/modules/cjs/helpers.js",
|
||||
"lib/internal/modules/cjs/loader.js",
|
||||
"lib/internal/modules/esm/create_dynamic_module.js",
|
||||
"lib/internal/modules/esm/get_format.js",
|
||||
"lib/internal/modules/esm/get_source.js",
|
||||
"lib/internal/modules/esm/loader.js",
|
||||
"lib/internal/modules/esm/module_job.js",
|
||||
"lib/internal/modules/esm/module_map.js",
|
||||
"lib/internal/modules/esm/resolve.js",
|
||||
"lib/internal/modules/esm/transform_source.js",
|
||||
"lib/internal/modules/esm/translators.js",
|
||||
"lib/internal/perf/event_loop_delay.js",
|
||||
"lib/internal/perf/event_loop_utilization.js",
|
||||
"lib/internal/perf/nodetiming.js",
|
||||
"lib/internal/perf/observe.js",
|
||||
"lib/internal/perf/performance.js",
|
||||
"lib/internal/perf/performance_entry.js",
|
||||
"lib/internal/perf/timerify.js",
|
||||
"lib/internal/perf/usertiming.js",
|
||||
"lib/internal/perf/utils.js",
|
||||
"lib/internal/per_context/domexception.js",
|
||||
"lib/internal/per_context/messageport.js",
|
||||
"lib/internal/per_context/primordials.js",
|
||||
"lib/internal/policy/manifest.js",
|
||||
"lib/internal/policy/sri.js",
|
||||
"lib/internal/process/esm_loader.js",
|
||||
"lib/internal/process/execution.js",
|
||||
"lib/internal/process/per_thread.js",
|
||||
"lib/internal/process/policy.js",
|
||||
"lib/internal/process/promises.js",
|
||||
"lib/internal/process/report.js",
|
||||
"lib/internal/process/signal.js",
|
||||
"lib/internal/process/task_queues.js",
|
||||
"lib/internal/process/warning.js",
|
||||
"lib/internal/process/worker_thread_only.js",
|
||||
"lib/internal/readline/callbacks.js",
|
||||
"lib/internal/readline/emitKeypressEvents.js",
|
||||
"lib/internal/readline/utils.js",
|
||||
"lib/internal/repl/await.js",
|
||||
"lib/internal/repl/history.js",
|
||||
"lib/internal/repl/utils.js",
|
||||
"lib/internal/source_map/prepare_stack_trace.js",
|
||||
"lib/internal/source_map/source_map.js",
|
||||
"lib/internal/source_map/source_map_cache.js",
|
||||
"lib/internal/streams/add-abort-signal.js",
|
||||
"lib/internal/streams/buffer_list.js",
|
||||
"lib/internal/streams/compose.js",
|
||||
"lib/internal/streams/destroy.js",
|
||||
"lib/internal/streams/duplex.js",
|
||||
"lib/internal/streams/duplexify.js",
|
||||
"lib/internal/streams/end-of-stream.js",
|
||||
"lib/internal/streams/from.js",
|
||||
"lib/internal/streams/lazy_transform.js",
|
||||
"lib/internal/streams/legacy.js",
|
||||
"lib/internal/streams/passthrough.js",
|
||||
"lib/internal/streams/pipeline.js",
|
||||
"lib/internal/streams/readable.js",
|
||||
"lib/internal/streams/state.js",
|
||||
"lib/internal/streams/transform.js",
|
||||
"lib/internal/streams/utils.js",
|
||||
"lib/internal/streams/writable.js",
|
||||
"lib/internal/test/binding.js",
|
||||
"lib/internal/test/transfer.js",
|
||||
"lib/internal/tls/parse-cert-string.js",
|
||||
"lib/internal/tls/secure-context.js",
|
||||
"lib/internal/tls/secure-pair.js",
|
||||
"lib/internal/util/comparisons.js",
|
||||
"lib/internal/util/debuglog.js",
|
||||
"lib/internal/util/inspect.js",
|
||||
"lib/internal/util/inspector.js",
|
||||
"lib/internal/util/iterable_weak_map.js",
|
||||
"lib/internal/util/types.js",
|
||||
"lib/internal/vm/module.js",
|
||||
"lib/internal/webstreams/encoding.js",
|
||||
"lib/internal/webstreams/queuingstrategies.js",
|
||||
"lib/internal/webstreams/readablestream.js",
|
||||
"lib/internal/webstreams/transfer.js",
|
||||
"lib/internal/webstreams/transformstream.js",
|
||||
"lib/internal/webstreams/util.js",
|
||||
"lib/internal/webstreams/writablestream.js",
|
||||
"lib/internal/worker/io.js",
|
||||
"lib/internal/worker/js_transferable.js",
|
||||
"lib/path/posix.js",
|
||||
"lib/path/win32.js",
|
||||
"lib/stream/consumers.js",
|
||||
"lib/stream/promises.js",
|
||||
"lib/stream/web.js",
|
||||
"lib/timers/promises.js",
|
||||
"lib/util/types.js"
|
||||
],
|
||||
"node_module_version": 99,
|
||||
"node_no_browser_globals": "false",
|
||||
"node_prefix": "/usr/local",
|
||||
"node_release_urlbase": "",
|
||||
"node_shared": "false",
|
||||
"node_shared_brotli": "false",
|
||||
"node_shared_cares": "false",
|
||||
"node_shared_http_parser": "false",
|
||||
"node_shared_libuv": "false",
|
||||
"node_shared_nghttp2": "false",
|
||||
"node_shared_nghttp3": "false",
|
||||
"node_shared_ngtcp2": "false",
|
||||
"node_shared_openssl": "false",
|
||||
"node_shared_zlib": "false",
|
||||
"node_tag": "",
|
||||
"node_target_type": "executable",
|
||||
"node_use_bundled_v8": "true",
|
||||
"node_use_dtrace": "false",
|
||||
"node_use_etw": "true",
|
||||
"node_use_node_code_cache": "false",
|
||||
"node_use_node_snapshot": "false",
|
||||
"node_use_openssl": "true",
|
||||
"node_use_v8_platform": "true",
|
||||
"node_with_ltcg": "false",
|
||||
"node_without_node_options": "false",
|
||||
"openssl_fips": "",
|
||||
"openssl_is_fips": "false",
|
||||
"openssl_no_asm": 1,
|
||||
"openssl_quic": "true",
|
||||
"ossfuzz": "false",
|
||||
"shlib_suffix": "so.93",
|
||||
"target_arch": "x64",
|
||||
"v8_enable_31bit_smis_on_64bit_arch": 0,
|
||||
"v8_enable_gdbjit": 0,
|
||||
"v8_enable_i18n_support": 1,
|
||||
"v8_enable_inspector": 1,
|
||||
"v8_enable_lite_mode": 0,
|
||||
"v8_enable_object_print": 1,
|
||||
"v8_enable_pointer_compression": 0,
|
||||
"v8_enable_webassembly": 1,
|
||||
"v8_no_strict_aliasing": 1,
|
||||
"v8_optimized_debug": 1,
|
||||
"v8_promise_internal_field_count": 1,
|
||||
"v8_random_seed": 0,
|
||||
"v8_trace_maps": 0,
|
||||
"v8_use_siphash": 1,
|
||||
"want_separate_host_toolset": 1,
|
||||
"nodedir": "C:\\Users\\Robson\\.electron-gyp\\16.0.8",
|
||||
"standalone_static_library": 1,
|
||||
"msbuild_path": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe",
|
||||
"runtime": "electron",
|
||||
"target": "16.0.8",
|
||||
"build_from_source": "true"
|
||||
}
|
||||
}
|
||||
154
build/node_simconnect.vcxproj
Normal file
154
build/node_simconnect.vcxproj
Normal file
@@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{3FB7EA61-704B-D0C6-7416-9EEBB1FC01F7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>node_simconnect</RootNamespace>
|
||||
<IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Locals">
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<ExecutablePath>$(ExecutablePath);$(MSBuildProjectDirectory)\..\bin\;$(MSBuildProjectDirectory)\..\bin\</ExecutablePath>
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<IntDir>$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.node</TargetExt>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.node</TargetExt>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.node</TargetExt>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.node</TargetExt>
|
||||
<TargetName>$(ProjectName)</TargetName>
|
||||
<TargetPath>$(OutDir)\$(ProjectName).node</TargetPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>C:\Users\Robson\.electron-gyp\16.0.8\include\node;C:\Users\Robson\.electron-gyp\16.0.8\src;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\config;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\openssl\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\uv\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\zlib;C:\Users\Robson\.electron-gyp\16.0.8\deps\v8\include;C:\MSFS SDK\SimConnect SDK\include;..\..\node-addon-api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-std:c++17 %(AdditionalOptions)</AdditionalOptions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4351;4355;4800;4251;4275;4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=node_simconnect;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;V8_DEPRECATION_WARNINGS;V8_IMMINENT_DEPRECATION_WARNINGS;_GLIBCXX_USE_CXX11_ABI=1;V8_COMPRESS_POINTERS;V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE;V8_31BIT_SMIS_ON_64BIT_ARCH;V8_REVERSE_JSARGS;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;OPENSSL_NO_ASM;NAPI_DISABLE_CPP_EXCEPTIONS;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<StringPooling>true</StringPooling>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\\Users\\Robson\\.electron-gyp\\16.0.8\\x64\\node.lib";C:\MSFS SDK\SimConnect SDK\lib\SimConnect.lib;Ws2_32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4199 %(AdditionalOptions)</AdditionalOptions>
|
||||
<DelayLoadDLLs>node.exe;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TargetExt>.node</TargetExt>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>C:\Users\Robson\.electron-gyp\16.0.8\include\node;C:\Users\Robson\.electron-gyp\16.0.8\src;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\config;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\openssl\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\uv\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\zlib;C:\Users\Robson\.electron-gyp\16.0.8\deps\v8\include;C:\MSFS SDK\SimConnect SDK\include;..\..\node-addon-api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=node_simconnect;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;V8_DEPRECATION_WARNINGS;V8_IMMINENT_DEPRECATION_WARNINGS;_GLIBCXX_USE_CXX11_ABI=1;V8_COMPRESS_POINTERS;V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE;V8_31BIT_SMIS_ON_64BIT_ARCH;V8_REVERSE_JSARGS;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;OPENSSL_NO_ASM;NAPI_DISABLE_CPP_EXCEPTIONS;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";DEBUG;_DEBUG;V8_ENABLE_CHECKS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y "C:\MSFS SDK\SimConnect SDK\lib\SimConnect.dll" "$(SolutionDir)Release\SimConnect.dll"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>C:\Users\Robson\.electron-gyp\16.0.8\include\node;C:\Users\Robson\.electron-gyp\16.0.8\src;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\config;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\openssl\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\uv\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\zlib;C:\Users\Robson\.electron-gyp\16.0.8\deps\v8\include;C:\MSFS SDK\SimConnect SDK\include;..\..\node-addon-api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-std:c++17 %(AdditionalOptions)</AdditionalOptions>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4351;4355;4800;4251;4275;4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<Optimization>Full</Optimization>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=node_simconnect;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;V8_DEPRECATION_WARNINGS;V8_IMMINENT_DEPRECATION_WARNINGS;_GLIBCXX_USE_CXX11_ABI=1;V8_COMPRESS_POINTERS;V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE;V8_31BIT_SMIS_ON_64BIT_ARCH;V8_REVERSE_JSARGS;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;OPENSSL_NO_ASM;NAPI_DISABLE_CPP_EXCEPTIONS;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<StringPooling>true</StringPooling>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\\Users\\Robson\\.electron-gyp\\16.0.8\\x64\\node.lib";C:\MSFS SDK\SimConnect SDK\lib\SimConnect.lib;Ws2_32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4199 %(AdditionalOptions)</AdditionalOptions>
|
||||
<DelayLoadDLLs>node.exe;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TargetExt>.node</TargetExt>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>C:\Users\Robson\.electron-gyp\16.0.8\include\node;C:\Users\Robson\.electron-gyp\16.0.8\src;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\config;C:\Users\Robson\.electron-gyp\16.0.8\deps\openssl\openssl\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\uv\include;C:\Users\Robson\.electron-gyp\16.0.8\deps\zlib;C:\Users\Robson\.electron-gyp\16.0.8\deps\v8\include;C:\MSFS SDK\SimConnect SDK\include;..\..\node-addon-api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=node_simconnect;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;V8_DEPRECATION_WARNINGS;V8_IMMINENT_DEPRECATION_WARNINGS;_GLIBCXX_USE_CXX11_ABI=1;V8_COMPRESS_POINTERS;V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE;V8_31BIT_SMIS_ON_64BIT_ARCH;V8_REVERSE_JSARGS;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;OPENSSL_NO_ASM;NAPI_DISABLE_CPP_EXCEPTIONS;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\binding.gyp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\simconnect_session.h" />
|
||||
<ClInclude Include="..\src\commons.h" />
|
||||
<ClInclude Include="..\src\binding.h" />
|
||||
<ClInclude Include="..\src\client_handler.h" />
|
||||
<ClInclude Include="..\src\dispatch_queue_worker.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\simconnect_session.cc">
|
||||
<ObjectFileName>$(IntDir)\src\simconnect_session.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\binding.cc">
|
||||
<ObjectFileName>$(IntDir)\src\binding.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\client_handler.cc">
|
||||
<ObjectFileName>$(IntDir)\src\client_handler.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\dispatch_queue_worker.cc">
|
||||
<ObjectFileName>$(IntDir)\src\dispatch_queue_worker.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-gyp\src\win_delay_load_hook.cc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
118
build/node_simconnect.vcxproj.filters
Normal file
118
build/node_simconnect.vcxproj.filters
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:">
|
||||
<UniqueIdentifier>{E5D29F2B-0177-9942-CA95-0FF700094F89}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos">
|
||||
<UniqueIdentifier>{D9C367F9-992E-BEF1-3EEB-5E8D506D42B8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos\_Newsky">
|
||||
<UniqueIdentifier>{29FA8469-EFDB-5351-9397-303AC3B1F6F9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos\_Newsky\newsky-frontend">
|
||||
<UniqueIdentifier>{F97D22CF-7980-7B2C-730F-39A46869D035}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos\_Newsky\newsky-frontend\node_modules">
|
||||
<UniqueIdentifier>{56DF7A98-063D-FB9D-485C-089023B4C16A}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-gyp">
|
||||
<UniqueIdentifier>{77348C0E-2034-7791-74D5-63C077DF5A3B}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-gyp\src">
|
||||
<UniqueIdentifier>{8CDEE807-BC53-E450-C8B8-4DEBB66742D4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="..">
|
||||
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\simconnect_session.cc">
|
||||
<Filter>..\src</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\src\simconnect_session.h">
|
||||
<Filter>..\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\commons.h">
|
||||
<Filter>..\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\binding.h">
|
||||
<Filter>..\src</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\src\binding.cc">
|
||||
<Filter>..\src</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\src\client_handler.h">
|
||||
<Filter>..\src</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\src\client_handler.cc">
|
||||
<Filter>..\src</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\src\dispatch_queue_worker.h">
|
||||
<Filter>..\src</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\src\dispatch_queue_worker.cc">
|
||||
<Filter>..\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-gyp\src\win_delay_load_hook.cc">
|
||||
<Filter>D:\GitRepos\_Newsky\newsky-frontend\node_modules\node-gyp\src</Filter>
|
||||
</ClCompile>
|
||||
<None Include="..\binding.gyp">
|
||||
<Filter>..</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
4
build/node_simconnect.vcxproj.user
Normal file
4
build/node_simconnect.vcxproj.user
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
73
examples/nodejs/example.js
Normal file
73
examples/nodejs/example.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const { SimConnect, PERIOD, SIMOBJECT_TYPE, DATATYPE } = require(`../..`);
|
||||
|
||||
const simConnect = new SimConnect()
|
||||
|
||||
tryToConnect();
|
||||
|
||||
function tryToConnect() {
|
||||
const ok = simConnect.open(
|
||||
"My app's name",
|
||||
onOpen,
|
||||
onQuit,
|
||||
onException,
|
||||
onError
|
||||
);
|
||||
if (!ok) {
|
||||
setTimeout(() => {
|
||||
console.log("Failed to connect. Retrying...")
|
||||
tryToConnect();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
function onOpen(client) {
|
||||
console.log(client.name, client.version);
|
||||
|
||||
client.subscribeToSystemEvent("Pause", value => {
|
||||
console.log("Pause status:", value)
|
||||
})
|
||||
|
||||
client.requestSystemState("AircraftLoaded", function(obj) {
|
||||
console.log("Loaded aircraft:", obj.string);
|
||||
});
|
||||
|
||||
const navInfoDefId = client.createDataDefinition([
|
||||
["ATC FLIGHT NUMBER", null, DATATYPE.STRINGV], // SIMCONNECT_DATATYPE_STRINGV
|
||||
["NAV NAME:1", null, DATATYPE.STRINGV], // SIMCONNECT_DATATYPE_STRINGV
|
||||
["Plane Latitude", "degrees"],
|
||||
["Plane Longitude", "degrees"],
|
||||
]);
|
||||
|
||||
client.requestDataOnSimObject(navInfoDefId, {
|
||||
period: PERIOD.ONCE, // SIMCONNECT_PERIOD_ONCE
|
||||
objectId: SIMOBJECT_TYPE.USER, // SIMCONNECT_OBJECT_ID_USER
|
||||
flags: 0, // SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT
|
||||
}, (data) => {
|
||||
console.log(data)
|
||||
});
|
||||
|
||||
client.requestDataOnSimObjectType([
|
||||
["ATC MODEL", null, DATATYPE.STRINGV], // SIMCONNECT_DATATYPE_STRINGV
|
||||
["Plane Latitude", "degrees"],
|
||||
["Plane Longitude", "degrees"]
|
||||
], {
|
||||
radius: 10000,
|
||||
type: SIMOBJECT_TYPE.AIRCRAFT // SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT
|
||||
}, (data) => {
|
||||
// Called for each aircraft
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
|
||||
function onQuit() {
|
||||
console.log("Quit :(")
|
||||
tryToConnect();
|
||||
}
|
||||
|
||||
function onException(ex) {
|
||||
console.log("Exception: ", ex)
|
||||
}
|
||||
|
||||
function onError(err) {
|
||||
console.log("Error: ", err)
|
||||
}
|
||||
81
index.d.ts
vendored
Normal file
81
index.d.ts
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
export class SimConnect {
|
||||
open(
|
||||
appName: string,
|
||||
onOpen: (client: Client) => void,
|
||||
onQuit: () => void,
|
||||
onException: (details: Exception) => void,
|
||||
onError: (details: Error) => void
|
||||
): boolean;
|
||||
}
|
||||
|
||||
interface Client {
|
||||
name: string;
|
||||
version: string;
|
||||
|
||||
requestDataOnSimObject(
|
||||
reqData: RequestDataObject[] | number,
|
||||
options: RequestDataOnSimObjectOptions,
|
||||
callback: (data: ResponseData) => void
|
||||
): void;
|
||||
|
||||
requestDataOnSimObjectType(
|
||||
reqData: RequestDataObject[] | number,
|
||||
options: RequestDataOnSimObjectTypeOptions,
|
||||
callback: (data: ResponseData) => void
|
||||
): void;
|
||||
|
||||
setDataOnSimObject(
|
||||
variableName: string,
|
||||
unit: string,
|
||||
value: number
|
||||
): void;
|
||||
|
||||
subscribeToSystemEvent(
|
||||
eventName: string,
|
||||
callback: (value: number) => void
|
||||
): void;
|
||||
|
||||
createDataDefinition(
|
||||
reqData: RequestDataObject[]
|
||||
): number;
|
||||
|
||||
requestSystemState(
|
||||
stateName: string,
|
||||
callback: (data: SystemState) => void
|
||||
): void;
|
||||
|
||||
close(): boolean;
|
||||
}
|
||||
|
||||
interface RequestDataOnSimObjectOptions {
|
||||
period: number,
|
||||
objectId: number,
|
||||
flags: number,
|
||||
}
|
||||
|
||||
interface RequestDataOnSimObjectTypeOptions {
|
||||
radius: number,
|
||||
type: number,
|
||||
}
|
||||
|
||||
type RequestDataObject = [
|
||||
variableName: string,
|
||||
units: string | null,
|
||||
dataType?: number
|
||||
]
|
||||
|
||||
interface ResponseData { [key:string]: number | string | undefined }
|
||||
|
||||
interface SystemState { integer: number, float: number, string: string }
|
||||
|
||||
interface Exception {
|
||||
readonly name: string;
|
||||
readonly dwException: number;
|
||||
readonly dwSendID: number;
|
||||
readonly dwIndex: number;
|
||||
}
|
||||
|
||||
interface Error {
|
||||
readonly message: string;
|
||||
readonly NTSTATUS: number;
|
||||
}
|
||||
31
index.js
Normal file
31
index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
if (process.platform !== `win32`) {
|
||||
throw `node-simconnect: The only supported platform is Windows (win32). Found: ${process.platform}`;
|
||||
}
|
||||
|
||||
let nodeSimconnect = undefined;
|
||||
|
||||
try {
|
||||
const TEXT_COLOR = '\x1b[30m\x1b[44m%s\x1b[0m';
|
||||
// Try loading manual build first
|
||||
try {
|
||||
nodeSimconnect = require(`./build/Release/node_simconnect`);
|
||||
console.info(TEXT_COLOR, `node-simconnect: Local Debug build loaded`);
|
||||
} catch {
|
||||
nodeSimconnect = require(`./build/Debug/node_simconnect`);
|
||||
console.info(TEXT_COLOR, `node-simconnect: Local Release build loaded`);
|
||||
}
|
||||
} catch (ex) {
|
||||
// If it fails, load the included binary
|
||||
console.info(`node-simconnect: Failed to load manual build (${ex.code})`);
|
||||
console.info(`node-simconnect: Loading pre-built binary`);
|
||||
if (process.arch === `x64`) {
|
||||
throw `node-simconnect: The pre-built binary only works with the 32-bit version of Node.js`;
|
||||
}
|
||||
nodeSimconnect = require(`./bin/win_ia32/node_simconnect`);
|
||||
console.info(`node-simconnect: Pre-built binary loaded`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SimConnect: nodeSimconnect.SimConnect,
|
||||
...require("./src/generated/constants")
|
||||
};
|
||||
39
package.json
Normal file
39
package.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "node-simconnect",
|
||||
"version": "2.0.0-beta.2",
|
||||
"description": "Wrapper for the SimConnect SDK for Flight Simulator X and Prepar3D (Windows only)",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"rebuild": "node-gyp configure rebuild --msvs_version=2019 --arch=ia32",
|
||||
"rebuild:dev": "npm run rebuild -- --debug"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"gypfile": false,
|
||||
"dependencies": {},
|
||||
"directories": {
|
||||
"example": "examples"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/EvenAR/node-simconnect.git"
|
||||
},
|
||||
"keywords": [
|
||||
"FSX",
|
||||
"P3D",
|
||||
"SDK",
|
||||
"SimConnect",
|
||||
"Prepar3D",
|
||||
"FlightSimulator",
|
||||
"Simulator"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/EvenAR/node-simconnect/issues"
|
||||
},
|
||||
"homepage": "https://github.com/EvenAR/node-simconnect#readme",
|
||||
"devDependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"node-addon-api": "^3.0.2",
|
||||
"node-gyp": "^7.1.0"
|
||||
}
|
||||
}
|
||||
58
scripts/generateConstants.js
Normal file
58
scripts/generateConstants.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const fs = require('fs');
|
||||
const readline = require('readline');
|
||||
|
||||
const INPUT_FILE = `${__dirname}/../SimConnect/inc/SimConnect.h`;
|
||||
const OUTPUT_DIRECTORY = `${__dirname}/../src/generated/`;
|
||||
const RELEVANT_ENUMS = ["PERIOD", "SIMOBJECT_TYPE", "DATATYPE"]; // Without the "SIMCONNECT_"-prefix
|
||||
|
||||
const inputFile = readline.createInterface({
|
||||
input: fs.createReadStream(INPUT_FILE),
|
||||
output: process.stdout,
|
||||
terminal: false
|
||||
});
|
||||
|
||||
if (!fs.existsSync(OUTPUT_DIRECTORY)){
|
||||
fs.mkdirSync(OUTPUT_DIRECTORY, { recursive: true });
|
||||
}
|
||||
|
||||
const ENUM_NAME_REGEX = /enum SIMCONNECT_(\S*) {/gm;
|
||||
const ENUM_VALUE_REGEX = /^\s*SIMCONNECT_([A-Z0-9_]*)((.*=\s*(.*)\s*),)?/;
|
||||
const ENUM_END_REGEX = /^\s*};\s*$/;
|
||||
|
||||
let valueCounter = 0;
|
||||
let currentEnumName = undefined;
|
||||
|
||||
const outputJson = {};
|
||||
|
||||
inputFile.on('line', (line) => {
|
||||
const enumNameMatch = ENUM_NAME_REGEX.exec(line);
|
||||
|
||||
if (enumNameMatch) {
|
||||
if (!RELEVANT_ENUMS.includes(enumNameMatch[1])) return;
|
||||
currentEnumName = enumNameMatch[1];
|
||||
outputJson[currentEnumName] = {};
|
||||
valueCounter = 0;
|
||||
} else if (currentEnumName) {
|
||||
if (ENUM_END_REGEX.exec(line)) {
|
||||
currentEnumName = undefined;
|
||||
} else {
|
||||
const nameMatch = ENUM_VALUE_REGEX.exec(line);
|
||||
if (nameMatch) {
|
||||
const valueName = nameMatch[1].replace(currentEnumName + "_", "");
|
||||
const fixedValue = nameMatch[4];
|
||||
if (fixedValue) {
|
||||
// Skip ahead and continue incrementing from this value
|
||||
valueCounter = Number.parseInt(fixedValue.trim());
|
||||
}
|
||||
outputJson[currentEnumName][valueName] = valueCounter;
|
||||
valueCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
inputFile.on("close", () => {
|
||||
const outputFile = fs.createWriteStream(`${OUTPUT_DIRECTORY}/constants.js`);
|
||||
outputFile.write(`// Autogenerated file [${new Date().toDateString()}]\r\n`);
|
||||
outputFile.write("module.exports = " + JSON.stringify(outputJson, null, 4))
|
||||
})
|
||||
6
scripts/install.js
Normal file
6
scripts/install.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const NOT_WINDOWS = process.platform !== "win32";
|
||||
const YELLOW = '\x1b[33m%s\x1b[0m';
|
||||
|
||||
if (NOT_WINDOWS) {
|
||||
console.log(YELLOW, `Warning: node-simconnect does not work on ${process.platform}`);
|
||||
}
|
||||
43
src/binding.cc
Normal file
43
src/binding.cc
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "binding.h"
|
||||
#include "simconnect_session.h"
|
||||
#include "client_handler.h"
|
||||
#include <iostream>
|
||||
|
||||
NodeSimconnect::NodeSimconnect(const Napi::CallbackInfo& info) : Napi::ObjectWrap<NodeSimconnect>(info) { }
|
||||
|
||||
Napi::Object NodeSimconnect::init(Napi::Env env, Napi::Object exports) {
|
||||
Napi::Function classFunction = DefineClass(env, "SimConnect", {
|
||||
InstanceMethod<&NodeSimconnect::open>("open")
|
||||
});
|
||||
|
||||
auto constructor = new Napi::FunctionReference();
|
||||
*constructor = Napi::Persistent(classFunction);
|
||||
exports.Set("SimConnect", classFunction);
|
||||
env.SetInstanceData<Napi::FunctionReference>(constructor);
|
||||
return exports;
|
||||
}
|
||||
|
||||
Napi::Value NodeSimconnect::open(const Napi::CallbackInfo& info) {
|
||||
auto appName = info[0].As<Napi::String>();
|
||||
|
||||
auto onOpen = info[1].As<Napi::Function>();
|
||||
auto onQuit = info[2].As<Napi::Function>();
|
||||
auto onException = info[3].As<Napi::Function>();
|
||||
auto onError = info[4].As<Napi::Function>();
|
||||
|
||||
if (!simHandler) {
|
||||
simHandler = Napi::Persistent(ClientHandler::init(info.Env()));
|
||||
}
|
||||
|
||||
ClientHandler* simHandlerInstance = ClientHandler::Unwrap(simHandler.Value().ToObject());
|
||||
bool ok = simHandlerInstance->open(appName.Utf8Value(), onOpen, onQuit, onException, onError);
|
||||
|
||||
return Napi::Boolean::New(info.Env(), ok);
|
||||
}
|
||||
|
||||
Napi::Object InitModule(Napi::Env env, Napi::Object exports) {
|
||||
NodeSimconnect::init(env, exports);
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(node_simconnect, InitModule);
|
||||
18
src/binding.h
Normal file
18
src/binding.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef BINDING_H
|
||||
#define BINDING_H
|
||||
|
||||
#include <napi.h>
|
||||
#include "commons.h"
|
||||
|
||||
class DispatchProgressWorker;
|
||||
|
||||
class NodeSimconnect : public Napi::ObjectWrap<NodeSimconnect> {
|
||||
public:
|
||||
NodeSimconnect(const Napi::CallbackInfo& info);
|
||||
static Napi::Object init(Napi::Env env, Napi::Object exports);
|
||||
private:
|
||||
Napi::ObjectReference simHandler;
|
||||
Napi::Value open(const Napi::CallbackInfo& info);
|
||||
};
|
||||
|
||||
#endif
|
||||
229
src/client_handler.cc
Normal file
229
src/client_handler.cc
Normal file
@@ -0,0 +1,229 @@
|
||||
#include "client_handler.h"
|
||||
#include "dispatch_queue_worker.h"
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
// Napi utils
|
||||
#define getOptionalElement(array, index, type, conversion, fallback) \
|
||||
array.Length() > index ? array[index].As<type>().conversion() : fallback;
|
||||
|
||||
ClientHandler::ClientHandler(const Napi::CallbackInfo& info)
|
||||
: Napi::ObjectWrap<ClientHandler>(info) {
|
||||
|
||||
}
|
||||
|
||||
ClientHandler::~ClientHandler() {
|
||||
|
||||
}
|
||||
|
||||
Napi::Object ClientHandler::init(Napi::Env env) {
|
||||
return DefineClass(env, "Client", {
|
||||
InstanceMethod("requestDataOnSimObject", &ClientHandler::requestDataOnSimObject, napi_enumerable),
|
||||
InstanceMethod("requestDataOnSimObjectType", &ClientHandler::requestDataOnSimObjectType, napi_enumerable),
|
||||
InstanceMethod("createDataDefinition", &ClientHandler::createDataDefinition, napi_enumerable),
|
||||
InstanceMethod("setDataOnSimObject", &ClientHandler::setDataOnSimObject, napi_enumerable),
|
||||
InstanceMethod("subscribeToSystemEvent", &ClientHandler::subscribeToSystemEvent, napi_enumerable),
|
||||
InstanceMethod("requestSystemState", &ClientHandler::requestSystemState, napi_enumerable),
|
||||
InstanceMethod("close", &ClientHandler::close, napi_enumerable),
|
||||
}).New({});
|
||||
}
|
||||
|
||||
bool ClientHandler::open(
|
||||
const std::string& appName,
|
||||
const Napi::Function& onOpen,
|
||||
const Napi::Function& onQuit,
|
||||
const Napi::Function& onException,
|
||||
const Napi::Function& onError
|
||||
) {
|
||||
if (simConnectSession.open(appName)) {
|
||||
openCallback = Napi::Persistent(onOpen);
|
||||
quitCallback = Napi::Persistent(onQuit);
|
||||
exceptionCallback = Napi::Persistent(onException);
|
||||
errorCallback = Napi::Persistent(onError);
|
||||
|
||||
dispatchQueueWorker = new DispatchQueueWorker(Env(), &simConnectSession, this);
|
||||
dispatchQueueWorker->Queue();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Napi::Value ClientHandler::requestSystemState(const Napi::CallbackInfo& info) {
|
||||
auto stateName = info[0].As<Napi::String>();
|
||||
auto callback = info[1].As<Napi::Function>();
|
||||
|
||||
auto requestId = simConnectSession.requestSystemState(stateName.Utf8Value());
|
||||
systemStateCallbacks[requestId] = Persistent(callback);
|
||||
|
||||
return info.Env().Undefined();
|
||||
};
|
||||
|
||||
Napi::Value ClientHandler::subscribeToSystemEvent(const Napi::CallbackInfo& info) {
|
||||
auto eventName = info[0].As<Napi::String>();
|
||||
auto callback = info[1].As<Napi::Function>();
|
||||
|
||||
auto eventId = simConnectSession.subscribeToSystemEvent(eventName.Utf8Value());
|
||||
systemEventCallbacks[eventId] = Persistent(callback);
|
||||
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
Napi::Value ClientHandler::requestDataOnSimObject(const Napi::CallbackInfo& info) {
|
||||
auto request = info[0];
|
||||
auto options = info[1].As<Napi::Object>();
|
||||
auto callback = info[2].As<Napi::Function>();
|
||||
|
||||
auto objectId = options.Get("objectId").As<Napi::Number>().Uint32Value();
|
||||
auto period = options.Get("period").As<Napi::Number>().Uint32Value();
|
||||
auto flags = options.Get("flags").As<Napi::Number>().Uint32Value();
|
||||
|
||||
unsigned int requestId;
|
||||
if (request.IsNumber()) {
|
||||
auto existingDataDefinitionId = request.As<Napi::Number>().Uint32Value();
|
||||
requestId = simConnectSession.requestDataOnSimObject(existingDataDefinitionId, objectId, period, flags);
|
||||
} else {
|
||||
auto requestedValues = request.As<Napi::Array>();
|
||||
requestId = simConnectSession.requestDataOnSimObject(toDatumRequests(requestedValues), objectId, period, flags);
|
||||
}
|
||||
|
||||
dataRequestCallbacks[requestId] = Persistent(callback);
|
||||
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
Napi::Value ClientHandler::createDataDefinition(const Napi::CallbackInfo& info) {
|
||||
auto requestedValues = info[0].As<Napi::Array>();
|
||||
auto definitionId = simConnectSession.createDataDefinition(toDatumRequests(requestedValues));
|
||||
|
||||
return Napi::Number::New(info.Env(), definitionId);
|
||||
};
|
||||
|
||||
Napi::Value ClientHandler::requestDataOnSimObjectType(const Napi::CallbackInfo& info) {
|
||||
auto request = info[0];
|
||||
auto options = info[1].As<Napi::Object>();
|
||||
auto callback = info[2].As<Napi::Function>();
|
||||
|
||||
auto radius = options.Get("radius").As<Napi::Number>().Uint32Value();
|
||||
auto type = options.Get("type").As<Napi::Number>().Uint32Value();
|
||||
|
||||
unsigned int requestId;
|
||||
if (request.IsNumber()) {
|
||||
auto existingDataDefinitionId = request.As<Napi::Number>().Uint32Value();
|
||||
requestId = simConnectSession.requestDataOnSimObjectType(existingDataDefinitionId, radius, type);
|
||||
} else {
|
||||
auto requestedValues = request.As<Napi::Array>();
|
||||
requestId = simConnectSession.requestDataOnSimObjectType(toDatumRequests(requestedValues), radius, type);
|
||||
}
|
||||
|
||||
dataRequestCallbacks[requestId] = Persistent(callback);
|
||||
|
||||
return info.Env().Undefined();
|
||||
};
|
||||
|
||||
Napi::Value ClientHandler::setDataOnSimObject(const Napi::CallbackInfo& info) {
|
||||
auto datumName = info[0].As<Napi::String>();
|
||||
auto unitName = info[1].As<Napi::String>();
|
||||
auto value = info[2].As<Napi::Number>().DoubleValue();
|
||||
|
||||
simConnectSession.setDataOnSimObject(datumName, unitName, value);
|
||||
|
||||
return info.Env().Undefined();
|
||||
};
|
||||
|
||||
Napi::Value ClientHandler::close(const Napi::CallbackInfo& info) {
|
||||
auto success = simConnectSession.close();
|
||||
|
||||
return Napi::Boolean::New(info.Env(), success);
|
||||
};
|
||||
|
||||
void ClientHandler::onOpen(std::shared_ptr<SimInfo> simInfo) {
|
||||
auto clientHandlerObject = Value();
|
||||
|
||||
clientHandlerObject.Set("name", Napi::String::New(Env(), simInfo->name));
|
||||
clientHandlerObject.Set("version", Napi::String::New(Env(), simInfo->version));
|
||||
|
||||
openCallback.Call({ clientHandlerObject });
|
||||
}
|
||||
|
||||
void ClientHandler::onException(std::shared_ptr<ExceptionInfo> exceptionInfo) {
|
||||
auto obj = Napi::Object::New(Env());
|
||||
obj.Set("dwException", Napi::Number::New(Env(), exceptionInfo->exception));
|
||||
obj.Set("dwSendID", Napi::Number::New(Env(), exceptionInfo->packetId));
|
||||
obj.Set("dwIndex", Napi::Number::New(Env(), exceptionInfo->parameterIndex));
|
||||
obj.Set("name", Napi::String::New(Env(), exceptionInfo->exceptionName));
|
||||
exceptionCallback.Call({obj});
|
||||
}
|
||||
|
||||
void ClientHandler::onError(std::shared_ptr<ErrorInfo> errorInfo) {
|
||||
auto obj = Napi::Object::New(Env());
|
||||
obj.Set("NTSTATUS", Napi::String::New(Env(), errorInfo->code));
|
||||
obj.Set("message", Napi::String::New(Env(), errorInfo->text));
|
||||
errorCallback.Call({obj});
|
||||
}
|
||||
|
||||
void ClientHandler::onQuit() {
|
||||
quitCallback.Call({});
|
||||
}
|
||||
|
||||
void ClientHandler::onSystemState(std::shared_ptr<SimSystemState> simSystemState) {
|
||||
auto obj = Napi::Object::New(Env());
|
||||
obj.Set("integer", Napi::Number::New(Env(), simSystemState->integerValue));
|
||||
obj.Set("float", Napi::Number::New(Env(), simSystemState->floatValue));
|
||||
obj.Set("string", Napi::String::New(Env(), simSystemState->stringValue.c_str()));
|
||||
|
||||
systemStateCallbacks[simSystemState->requestId].Call({obj});
|
||||
}
|
||||
|
||||
void ClientHandler::onEvent(std::shared_ptr<SimEvent> simEvent) {
|
||||
auto value = Napi::Number::New(Env(), simEvent->value);
|
||||
systemEventCallbacks[simEvent->type].Call({value});
|
||||
}
|
||||
|
||||
void ClientHandler::onSimobjectData(std::shared_ptr<SimobjectDataBatch> simobjectDataBatch) {
|
||||
auto obj = Napi::Object::New(Env());
|
||||
|
||||
for ( auto const& [datumName, pair] : simobjectDataBatch->values ) {
|
||||
DatumType datumType = pair.first;
|
||||
std::shared_ptr<const void> pDatumValue = pair.second;
|
||||
|
||||
switch (datumType) {
|
||||
case DatumType::Int32: {
|
||||
obj.Set(datumName, Napi::Number::New(Env(), *std::static_pointer_cast<const int32_t>(pDatumValue)));
|
||||
} break;
|
||||
case DatumType::Int64: {
|
||||
obj.Set(datumName, Napi::Number::New(Env(), *std::static_pointer_cast<const int64_t>(pDatumValue)));
|
||||
} break;
|
||||
case DatumType::Double: {
|
||||
obj.Set(datumName, Napi::Number::New(Env(), *std::static_pointer_cast<const double>(pDatumValue)));
|
||||
} break;
|
||||
case DatumType::Text: {
|
||||
obj.Set(datumName, Napi::String::New(Env(), std::static_pointer_cast<const std::string>(pDatumValue)->c_str()));
|
||||
} break;
|
||||
default: {
|
||||
obj.Set("UNKNOWN_VALUE", Napi::String::New(Env(), "?"));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
dataRequestCallbacks[simobjectDataBatch->id].Call({obj});
|
||||
};
|
||||
|
||||
std::vector<DatumRequest> ClientHandler::toDatumRequests(Napi::Array requestedValues) {
|
||||
std::vector<DatumRequest> datumRequests;
|
||||
for (unsigned int i = 0; i < requestedValues.Length(); i++) {
|
||||
auto element = requestedValues.Get(i);
|
||||
if(element.IsArray()) {
|
||||
auto options = element.As<Napi::Array>();
|
||||
auto datumName = options.Get("0").As<Napi::String>().Utf8Value();
|
||||
auto unitName = options.Get("1").IsNull() ? std::nullopt : std::optional<std::string>{ options.Get("1").As<Napi::String>().Utf8Value() };
|
||||
auto dataType = options.Get("2").IsUndefined() ? std::nullopt : std::optional<unsigned int>{ options.Get("2").As<Napi::Number>().Uint32Value() };
|
||||
|
||||
datumRequests.push_back({
|
||||
datumName,
|
||||
unitName,
|
||||
dataType
|
||||
});
|
||||
}
|
||||
}
|
||||
return datumRequests;
|
||||
};
|
||||
60
src/client_handler.h
Normal file
60
src/client_handler.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef SIM_HANDLER_H
|
||||
#define SIM_HANDLER_H
|
||||
|
||||
#include <napi.h>
|
||||
#include "simconnect_session.h"
|
||||
#include "event_handler_interface.h"
|
||||
|
||||
class DispatchQueueWorker;
|
||||
|
||||
class ClientHandler : public Napi::ObjectWrap<ClientHandler>, EventHandlerInterface {
|
||||
|
||||
public:
|
||||
ClientHandler(const Napi::CallbackInfo& info);
|
||||
static Napi::Object init(Napi::Env env);
|
||||
|
||||
bool open(
|
||||
const std::string& appName,
|
||||
const Napi::Function& onOpen,
|
||||
const Napi::Function& onQuit,
|
||||
const Napi::Function& onException,
|
||||
const Napi::Function& onError
|
||||
);
|
||||
|
||||
Napi::Value requestSystemState(const Napi::CallbackInfo& info);
|
||||
Napi::Value requestDataOnSimObject(const Napi::CallbackInfo& info);
|
||||
Napi::Value createDataDefinition(const Napi::CallbackInfo& info);
|
||||
Napi::Value requestDataOnSimObjectType(const Napi::CallbackInfo& info);
|
||||
Napi::Value setDataOnSimObject(const Napi::CallbackInfo& info);
|
||||
Napi::Value subscribeToSystemEvent(const Napi::CallbackInfo& info);
|
||||
Napi::Value close(const Napi::CallbackInfo& info);
|
||||
|
||||
~ClientHandler();
|
||||
|
||||
private:
|
||||
SimConnectSession simConnectSession;
|
||||
|
||||
Napi::FunctionReference openCallback;
|
||||
Napi::FunctionReference quitCallback;
|
||||
Napi::FunctionReference exceptionCallback;
|
||||
Napi::FunctionReference errorCallback;
|
||||
|
||||
std::unordered_map<int32_t, Napi::FunctionReference> systemStateCallbacks;
|
||||
std::unordered_map<int32_t, Napi::FunctionReference> systemEventCallbacks;
|
||||
std::unordered_map<int32_t, Napi::FunctionReference> dataRequestCallbacks;
|
||||
|
||||
DispatchQueueWorker* dispatchQueueWorker = nullptr;
|
||||
std::vector<DatumRequest> toDatumRequests(Napi::Array requestedValues);
|
||||
|
||||
// Required functions defined EventHandlerInterface
|
||||
void onOpen(std::shared_ptr<SimInfo> simInfo);
|
||||
void onQuit();
|
||||
void onException(std::shared_ptr<ExceptionInfo> exceptionInfo);
|
||||
void onError(std::shared_ptr<ErrorInfo> errorInfo);
|
||||
void onSystemState(std::shared_ptr<SimSystemState> simSystemState);
|
||||
void onEvent(std::shared_ptr<SimEvent> simEvent);
|
||||
void onSimobjectData(std::shared_ptr<SimobjectDataBatch> simobjectDataBatch);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
74
src/commons.h
Normal file
74
src/commons.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef COMMONS_H
|
||||
#define COMMONS_H
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
|
||||
enum DispatchContentType {
|
||||
Nothing,
|
||||
Exception,
|
||||
Error,
|
||||
Unkn,
|
||||
open,
|
||||
Quit,
|
||||
EventId,
|
||||
SimobjectData,
|
||||
SystemState
|
||||
};
|
||||
|
||||
struct DispatchContent {
|
||||
DispatchContentType type;
|
||||
std::shared_ptr<void> payload;
|
||||
};
|
||||
|
||||
enum DatumType {
|
||||
Text,
|
||||
Int32,
|
||||
Int64,
|
||||
Double,
|
||||
Float
|
||||
};
|
||||
|
||||
struct SimobjectDataBatch {
|
||||
unsigned int id;
|
||||
std::map<std::string, std::pair<DatumType, std::shared_ptr<const void>>> values;
|
||||
};
|
||||
|
||||
struct SimInfo {
|
||||
std::string name;
|
||||
std::string version;
|
||||
};
|
||||
|
||||
struct ExceptionInfo {
|
||||
unsigned int exception;
|
||||
unsigned int packetId;
|
||||
unsigned int parameterIndex;
|
||||
std::string exceptionName;
|
||||
};
|
||||
|
||||
struct ErrorInfo {
|
||||
std::string code;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
struct DatumRequest {
|
||||
std::string datumName;
|
||||
std::optional<std::string> unitName;
|
||||
std::optional<unsigned int> datumType;
|
||||
};
|
||||
|
||||
struct SimEvent {
|
||||
unsigned long type;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
struct SimSystemState {
|
||||
unsigned int requestId;
|
||||
unsigned int integerValue;
|
||||
float floatValue;
|
||||
std::string stringValue;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
69
src/dispatch_queue_worker.cc
Normal file
69
src/dispatch_queue_worker.cc
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "dispatch_queue_worker.h"
|
||||
#include "commons.h"
|
||||
#include "event_handler_interface.h"
|
||||
#include "simconnect_session.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
|
||||
DispatchQueueWorker::DispatchQueueWorker(Napi::Env env, SimConnectSession* simConnect, EventHandlerInterface* eventHandler)
|
||||
: AsyncProgressQueueWorker<DispatchContent>(env)
|
||||
, eventHandler(eventHandler)
|
||||
, simConnect(simConnect) { }
|
||||
|
||||
DispatchQueueWorker::~DispatchQueueWorker() {
|
||||
}
|
||||
|
||||
void DispatchQueueWorker::Execute(const ExecutionProgress& progress) {
|
||||
// This code will be executed on the worker thread
|
||||
while (true) {
|
||||
DispatchContent nextDispatch = simConnect->NextDispatch();
|
||||
if (nextDispatch.type == DispatchContentType::Nothing) {
|
||||
Sleep(1);
|
||||
} else {
|
||||
progress.Send(&nextDispatch, 1);
|
||||
}
|
||||
if (nextDispatch.type == DispatchContentType::Error || nextDispatch.type == DispatchContentType::Quit) {
|
||||
break; // This will make this worker destroy itself
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is executed on the main (JS) thread
|
||||
void DispatchQueueWorker::OnProgress(const DispatchContent* dispatch, size_t count) {
|
||||
switch (dispatch->type) {
|
||||
case DispatchContentType::Nothing: break;
|
||||
case DispatchContentType::Error: {
|
||||
this->eventHandler->onError(std::static_pointer_cast<ErrorInfo>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::Quit: {
|
||||
this->eventHandler->onQuit();
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::Exception: {
|
||||
this->eventHandler->onException(std::static_pointer_cast<ExceptionInfo>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::open: {
|
||||
this->eventHandler->onOpen(std::static_pointer_cast<SimInfo>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::EventId: {
|
||||
this->eventHandler->onEvent(std::static_pointer_cast<SimEvent>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::SystemState: {
|
||||
this->eventHandler->onSystemState(std::static_pointer_cast<SimSystemState>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
case DispatchContentType::SimobjectData: {
|
||||
this->eventHandler->onSimobjectData(std::static_pointer_cast<SimobjectDataBatch>(dispatch->payload));
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
std::cout << "Got unknown event " << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
23
src/dispatch_queue_worker.h
Normal file
23
src/dispatch_queue_worker.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef DISPATCH_QUEUE_WORKER_H
|
||||
#define DISPATCH_QUEUE_WORKER_H
|
||||
|
||||
#include <napi.h>
|
||||
|
||||
class EventHandlerInterface;
|
||||
class SimConnectSession;
|
||||
struct DispatchContent;
|
||||
|
||||
class DispatchQueueWorker : public Napi::AsyncProgressQueueWorker<DispatchContent> {
|
||||
|
||||
public:
|
||||
DispatchQueueWorker(Napi::Env env, SimConnectSession* simConnect, EventHandlerInterface* eventHandler);
|
||||
~DispatchQueueWorker();
|
||||
void Execute(const ExecutionProgress& progress);
|
||||
void OnProgress(const DispatchContent* dispatch, size_t /* count */);
|
||||
|
||||
private:
|
||||
EventHandlerInterface* eventHandler;
|
||||
SimConnectSession* simConnect;
|
||||
};
|
||||
|
||||
#endif
|
||||
12
src/event_handler_interface.h
Normal file
12
src/event_handler_interface.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "commons.h"
|
||||
|
||||
class EventHandlerInterface {
|
||||
public:
|
||||
virtual void onOpen(std::shared_ptr<SimInfo> data) = 0;
|
||||
virtual void onQuit() = 0;
|
||||
virtual void onException(std::shared_ptr<ExceptionInfo> data) = 0;
|
||||
virtual void onError(std::shared_ptr<ErrorInfo> data) = 0;
|
||||
virtual void onSystemState(std::shared_ptr<SimSystemState> data) = 0;
|
||||
virtual void onEvent(std::shared_ptr<SimEvent> data) = 0;
|
||||
virtual void onSimobjectData(std::shared_ptr<SimobjectDataBatch> data) = 0;
|
||||
};
|
||||
38
src/generated/constants.js
Normal file
38
src/generated/constants.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// Autogenerated file [Wed Nov 25 2020]
|
||||
module.exports = {
|
||||
"DATATYPE": {
|
||||
"INVALID": 0,
|
||||
"INT32": 1,
|
||||
"INT64": 2,
|
||||
"FLOAT32": 3,
|
||||
"FLOAT64": 4,
|
||||
"STRING8": 5,
|
||||
"STRING32": 6,
|
||||
"STRING64": 7,
|
||||
"STRING128": 8,
|
||||
"STRING256": 9,
|
||||
"STRING260": 10,
|
||||
"STRINGV": 11,
|
||||
"INITPOSITION": 12,
|
||||
"MARKERSTATE": 13,
|
||||
"WAYPOINT": 14,
|
||||
"LATLONALT": 15,
|
||||
"XYZ": 16,
|
||||
"MAX": 17
|
||||
},
|
||||
"SIMOBJECT_TYPE": {
|
||||
"USER": 0,
|
||||
"ALL": 1,
|
||||
"AIRCRAFT": 2,
|
||||
"HELICOPTER": 3,
|
||||
"BOAT": 4,
|
||||
"GROUND": 5
|
||||
},
|
||||
"PERIOD": {
|
||||
"NEVER": 0,
|
||||
"ONCE": 1,
|
||||
"VISUAL_FRAME": 2,
|
||||
"SIM_FRAME": 3,
|
||||
"SECOND": 4
|
||||
}
|
||||
}
|
||||
494
src/simconnect_session.cc
Normal file
494
src/simconnect_session.cc
Normal file
@@ -0,0 +1,494 @@
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <SimConnect.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
#include "simconnect_session.h"
|
||||
|
||||
#define check(hr) { if(hr != S_OK) handleError(__FUNCTION__, hr); }
|
||||
|
||||
std::map<SIMCONNECT_EXCEPTION, const char*> exceptionNames = {
|
||||
{ SIMCONNECT_EXCEPTION_NONE, "SIMCONNECT_EXCEPTION_NONE" },
|
||||
{ SIMCONNECT_EXCEPTION_ERROR, "SIMCONNECT_EXCEPTION_ERROR" },
|
||||
{ SIMCONNECT_EXCEPTION_SIZE_MISMATCH, "SIMCONNECT_EXCEPTION_SIZE_MISMATCH" },
|
||||
{ SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, "SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID" },
|
||||
{ SIMCONNECT_EXCEPTION_UNOPENED, "SIMCONNECT_EXCEPTION_UNOPENED" },
|
||||
{ SIMCONNECT_EXCEPTION_VERSION_MISMATCH, "SIMCONNECT_EXCEPTION_VERSION_MISMATCH" },
|
||||
{ SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, "SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS" },
|
||||
{ SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, "SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED" },
|
||||
{ SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, "SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES" },
|
||||
{ SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, "SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE" },
|
||||
{ SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, "SIMCONNECT_EXCEPTION_TOO_MANY_MAPS" },
|
||||
{ SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, "SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS" },
|
||||
{ SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, "SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS" },
|
||||
{ SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, "SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT" },
|
||||
{ SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, "SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR" },
|
||||
{ SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, "SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION" },
|
||||
{ SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, "SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION" },
|
||||
{ SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, "SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION" },
|
||||
{ SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, "SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE" },
|
||||
{ SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, "SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE" },
|
||||
{ SIMCONNECT_EXCEPTION_DATA_ERROR, "SIMCONNECT_EXCEPTION_DATA_ERROR" },
|
||||
{ SIMCONNECT_EXCEPTION_INVALID_ARRAY, "SIMCONNECT_EXCEPTION_INVALID_ARRAY" },
|
||||
{ SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, "SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED" },
|
||||
{ SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, "SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE" },
|
||||
{ SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, "SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION" },
|
||||
{ SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, "SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED" },
|
||||
{ SIMCONNECT_EXCEPTION_INVALID_ENUM, "SIMCONNECT_EXCEPTION_INVALID_ENUM" },
|
||||
{ SIMCONNECT_EXCEPTION_DEFINITION_ERROR, "SIMCONNECT_EXCEPTION_DEFINITION_ERROR" },
|
||||
{ SIMCONNECT_EXCEPTION_DUPLICATE_ID, "SIMCONNECT_EXCEPTION_DUPLICATE_ID" },
|
||||
{ SIMCONNECT_EXCEPTION_DATUM_ID, "SIMCONNECT_EXCEPTION_DATUM_ID" },
|
||||
{ SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, "SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS" },
|
||||
{ SIMCONNECT_EXCEPTION_ALREADY_CREATED, "SIMCONNECT_EXCEPTION_ALREADY_CREATED" },
|
||||
{ SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE, "SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE" },
|
||||
{ SIMCONNECT_EXCEPTION_OBJECT_CONTAINER, "SIMCONNECT_EXCEPTION_OBJECT_CONTAINER" },
|
||||
{ SIMCONNECT_EXCEPTION_OBJECT_AI, "SIMCONNECT_EXCEPTION_OBJECT_AI" },
|
||||
{ SIMCONNECT_EXCEPTION_OBJECT_ATC, "SIMCONNECT_EXCEPTION_OBJECT_ATC" },
|
||||
{ SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE, "SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE" }
|
||||
};
|
||||
|
||||
std::map<SIMCONNECT_DATATYPE, int> sizeMap = {
|
||||
{ SIMCONNECT_DATATYPE_INT32, 4 },
|
||||
{ SIMCONNECT_DATATYPE_INT64, 8 },
|
||||
{ SIMCONNECT_DATATYPE_FLOAT32, 4 },
|
||||
{ SIMCONNECT_DATATYPE_FLOAT64, 8 },
|
||||
{ SIMCONNECT_DATATYPE_STRING8, 8 },
|
||||
{ SIMCONNECT_DATATYPE_STRING32, 32 },
|
||||
{ SIMCONNECT_DATATYPE_STRING64, 64 },
|
||||
{ SIMCONNECT_DATATYPE_STRING128, 128 },
|
||||
{ SIMCONNECT_DATATYPE_STRING256, 256 },
|
||||
{ SIMCONNECT_DATATYPE_STRING260, 260 }
|
||||
};
|
||||
|
||||
unsigned int nextEventId = 0;
|
||||
unsigned int nextRequestId = 0;
|
||||
unsigned int nextDataDefinitionId = 0;
|
||||
|
||||
struct DataBatchDefinition {
|
||||
SIMCONNECT_DATA_DEFINITION_ID id;
|
||||
size_t num_values;
|
||||
std::vector<std::string> datum_names;
|
||||
std::vector<SIMCONNECT_DATATYPE> datum_types;
|
||||
};
|
||||
|
||||
std::map<DWORD, DataBatchDefinition> dataDefinitions;
|
||||
|
||||
SimConnectSession::SimConnectSession() { }
|
||||
|
||||
bool SimConnectSession::open(const std::string& appName) {
|
||||
this->hSimConnect = NULL;
|
||||
this->fatalError = nullptr;
|
||||
|
||||
HRESULT hr = SimConnect_Open(&hSimConnect, appName.c_str(), NULL, 0, 0, 0);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
};
|
||||
|
||||
DispatchContent SimConnectSession::NextDispatch() {
|
||||
if (this->fatalError != nullptr) {
|
||||
return { DispatchContentType::Error, this->fatalError };
|
||||
}
|
||||
|
||||
SIMCONNECT_RECV *pData;
|
||||
DWORD cbData;
|
||||
|
||||
HRESULT hr = SimConnect_GetNextDispatch(hSimConnect, &pData, &cbData);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
return this->process(pData, cbData);
|
||||
} else if (NT_ERROR(hr)) {
|
||||
check(hr);
|
||||
return { DispatchContentType::Error, this->fatalError };
|
||||
} else {
|
||||
return { DispatchContentType::Nothing, nullptr };
|
||||
}
|
||||
}
|
||||
|
||||
DispatchContent SimConnectSession::process(SIMCONNECT_RECV* pData, DWORD cbData) {
|
||||
SIMCONNECT_RECV_ID eventId = (SIMCONNECT_RECV_ID)pData->dwID;
|
||||
|
||||
switch (eventId) {
|
||||
case SIMCONNECT_RECV_ID_NULL:
|
||||
return { DispatchContentType::Nothing, nullptr };
|
||||
case SIMCONNECT_RECV_ID_EXCEPTION:
|
||||
return { DispatchContentType::Exception, this->getExceptionInfo(pData) };
|
||||
case SIMCONNECT_RECV_ID_OPEN:
|
||||
return { DispatchContentType::open, this->getSimInfo(pData) };
|
||||
case SIMCONNECT_RECV_ID_QUIT:
|
||||
return { DispatchContentType::Quit, nullptr };
|
||||
case SIMCONNECT_RECV_ID_SYSTEM_STATE:
|
||||
return { DispatchContentType::SystemState, this->getSystemState(pData) };
|
||||
case SIMCONNECT_RECV_ID_EVENT:
|
||||
return { DispatchContentType::EventId, this->getEvent(pData) };
|
||||
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA:
|
||||
return { DispatchContentType::SimobjectData, this->getSimObjectData(pData, cbData) };
|
||||
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE:
|
||||
return { DispatchContentType::SimobjectData, this->getSimObjectData(pData, cbData) };
|
||||
default: {
|
||||
return { DispatchContentType::Unkn, nullptr };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::subscribeToSystemEvent(const std::string& eventName) {
|
||||
HRESULT hr = SimConnect_SubscribeToSystemEvent(this->hSimConnect, nextEventId, eventName.c_str());
|
||||
check(hr);
|
||||
return nextEventId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::requestSystemState(std::string stateName) {
|
||||
HRESULT hr = SimConnect_RequestSystemState(hSimConnect, nextRequestId, stateName.c_str());
|
||||
check(hr);
|
||||
return nextRequestId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::flightLoad(std::string fileName) {
|
||||
HRESULT hr = SimConnect_FlightLoad(hSimConnect, fileName.c_str());
|
||||
check(hr);
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::transmitClientEvent(std::string eventName, unsigned int objectId, int data) {
|
||||
HRESULT hr = SimConnect_MapClientEventToSimEvent(hSimConnect, nextEventId, eventName.c_str());
|
||||
|
||||
check(hr);
|
||||
|
||||
hr = SimConnect_TransmitClientEvent(
|
||||
hSimConnect,
|
||||
objectId,
|
||||
nextEventId,
|
||||
data,
|
||||
SIMCONNECT_GROUP_PRIORITY_HIGHEST,
|
||||
SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextEventId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::createDataDefinition(std::vector<DatumRequest> datumRequests) {
|
||||
DataBatchDefinition newDefinition = generateDataDefinition(datumRequests);
|
||||
dataDefinitions[newDefinition.id] = newDefinition;
|
||||
return newDefinition.id;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::requestDataOnSimObject(std::vector<DatumRequest> datumRequests, unsigned int objectId, unsigned int period, unsigned int flags) {
|
||||
|
||||
DataBatchDefinition newDataDefinition = generateDataDefinition(datumRequests);
|
||||
|
||||
dataDefinitions[newDataDefinition.id] = newDataDefinition;
|
||||
|
||||
HRESULT hr = SimConnect_RequestDataOnSimObject(
|
||||
hSimConnect,
|
||||
nextRequestId,
|
||||
newDataDefinition.id,
|
||||
objectId,
|
||||
SIMCONNECT_PERIOD(period),
|
||||
flags
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextRequestId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::requestDataOnSimObject(unsigned int existingDataDefinitionId, unsigned int objectId, unsigned int period, unsigned int flags) {
|
||||
|
||||
HRESULT hr = SimConnect_RequestDataOnSimObject(
|
||||
hSimConnect,
|
||||
nextRequestId,
|
||||
dataDefinitions[existingDataDefinitionId].id,
|
||||
objectId,
|
||||
SIMCONNECT_PERIOD(period),
|
||||
flags
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextRequestId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::requestDataOnSimObjectType(std::vector<DatumRequest> datumRequests, unsigned int radius, unsigned int simobjectType) {
|
||||
DataBatchDefinition newDataDefinition = generateDataDefinition(datumRequests);
|
||||
|
||||
dataDefinitions[newDataDefinition.id] = newDataDefinition;
|
||||
HRESULT hr = SimConnect_RequestDataOnSimObjectType(
|
||||
hSimConnect,
|
||||
nextRequestId,
|
||||
newDataDefinition.id,
|
||||
radius,
|
||||
SIMCONNECT_SIMOBJECT_TYPE(simobjectType)
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextRequestId++;
|
||||
}
|
||||
|
||||
|
||||
unsigned int SimConnectSession::requestDataOnSimObjectType(unsigned int existingDataDefinitionId, unsigned int radius, unsigned int simobjectType) {
|
||||
HRESULT hr = SimConnect_RequestDataOnSimObjectType(
|
||||
hSimConnect,
|
||||
nextRequestId,
|
||||
dataDefinitions[existingDataDefinitionId].id,
|
||||
radius,
|
||||
SIMCONNECT_SIMOBJECT_TYPE(simobjectType)
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextRequestId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::setDataOnSimObject(std::string datumName, std::string unitsName, double value) {
|
||||
HRESULT hr = SimConnect_AddToDataDefinition(
|
||||
hSimConnect,
|
||||
nextDataDefinitionId,
|
||||
datumName.c_str(),
|
||||
unitsName.c_str()
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
hr = SimConnect_SetDataOnSimObject(
|
||||
hSimConnect,
|
||||
nextDataDefinitionId,
|
||||
SIMCONNECT_OBJECT_ID_USER,
|
||||
0,
|
||||
0,
|
||||
sizeof(value),
|
||||
&value
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
return nextDataDefinitionId++;
|
||||
}
|
||||
|
||||
unsigned int SimConnectSession::setAircraftInitialPosition(
|
||||
double lat,
|
||||
double lng,
|
||||
double altitude,
|
||||
double pitch,
|
||||
double bank,
|
||||
double heading,
|
||||
bool onGround,
|
||||
unsigned long airspeed
|
||||
) {
|
||||
SIMCONNECT_DATA_INITPOSITION init = {
|
||||
lat,
|
||||
lng,
|
||||
altitude,
|
||||
pitch,
|
||||
bank,
|
||||
heading,
|
||||
onGround ? 1UL : 0UL,
|
||||
airspeed
|
||||
};
|
||||
|
||||
HRESULT hr = SimConnect_AddToDataDefinition(
|
||||
hSimConnect,
|
||||
nextDataDefinitionId,
|
||||
"Initial Position",
|
||||
NULL,
|
||||
SIMCONNECT_DATATYPE_INITPOSITION
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
hr = SimConnect_SetDataOnSimObject(
|
||||
hSimConnect,
|
||||
nextDataDefinitionId,
|
||||
SIMCONNECT_OBJECT_ID_USER,
|
||||
0,
|
||||
0,
|
||||
sizeof(init),
|
||||
&init
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
nextDataDefinitionId++;
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
std::shared_ptr<SimEvent> SimConnectSession::getEvent(SIMCONNECT_RECV* pData) {
|
||||
SIMCONNECT_RECV_EVENT* myEvent = (SIMCONNECT_RECV_EVENT*)pData;
|
||||
auto info = std::make_shared<SimEvent>();
|
||||
info->type = myEvent->uEventID;
|
||||
info->value = myEvent->dwData;
|
||||
return info;
|
||||
}
|
||||
|
||||
std::shared_ptr<SimSystemState> SimConnectSession::getSystemState(SIMCONNECT_RECV* pData) {
|
||||
SIMCONNECT_RECV_SYSTEM_STATE* pState = (SIMCONNECT_RECV_SYSTEM_STATE*)pData;
|
||||
|
||||
auto simSystemState = std::make_shared<SimSystemState>(
|
||||
SimSystemState{
|
||||
pState->dwRequestID,
|
||||
pState->dwInteger,
|
||||
pState->fFloat,
|
||||
std::string(pState->szString)
|
||||
}
|
||||
);
|
||||
|
||||
return simSystemState;
|
||||
}
|
||||
|
||||
std::shared_ptr<SimInfo> SimConnectSession::getSimInfo(SIMCONNECT_RECV* pData) {
|
||||
SIMCONNECT_RECV_OPEN *pOpen = (SIMCONNECT_RECV_OPEN *)pData;
|
||||
|
||||
char simconnVersion[32];
|
||||
sprintf(simconnVersion, "%d.%d.%d.%d", pOpen->dwSimConnectVersionMajor, pOpen->dwSimConnectVersionMinor, pOpen->dwSimConnectBuildMajor, pOpen->dwSimConnectBuildMinor);
|
||||
|
||||
std::string version = std::string(simconnVersion);
|
||||
std::string simName = std::string(pOpen->szApplicationName);
|
||||
|
||||
auto info = std::make_shared<SimInfo>();
|
||||
info->name = std::string(pOpen->szApplicationName);
|
||||
info->version = std::string(simconnVersion);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::shared_ptr<ExceptionInfo> SimConnectSession::getExceptionInfo(SIMCONNECT_RECV* pData) {
|
||||
SIMCONNECT_RECV_EXCEPTION *exception = (SIMCONNECT_RECV_EXCEPTION *)pData;
|
||||
|
||||
auto info = std::shared_ptr<ExceptionInfo>();
|
||||
info->exception = exception->dwException;
|
||||
info->packetId = exception->dwSendID;
|
||||
info->parameterIndex = exception->dwIndex;
|
||||
info->exceptionName = exceptionNames[SIMCONNECT_EXCEPTION(info->exception)];
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::shared_ptr<SimobjectDataBatch> SimConnectSession::getSimObjectData(SIMCONNECT_RECV* pSimData, DWORD cbData) {
|
||||
SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA *)pSimData;
|
||||
DataBatchDefinition batch = dataDefinitions[pObjData->dwDefineID];
|
||||
|
||||
std::vector<SIMCONNECT_DATATYPE> datumTypes = batch.datum_types;
|
||||
std::vector<std::string> datumNames = batch.datum_names;
|
||||
std::map<std::string, std::pair<DatumType, std::shared_ptr<const void>>> output;
|
||||
|
||||
unsigned int dataValueOffset = 0;
|
||||
|
||||
for (unsigned int i = 0; i < batch.num_values; i++) {
|
||||
unsigned int datumSize = 0;
|
||||
std::string datumName = datumNames.at(i);
|
||||
SIMCONNECT_DATATYPE datumType = datumTypes.at(i);
|
||||
char* pData = (char*)(&pObjData->dwData) + dataValueOffset;
|
||||
|
||||
if (datumType == SIMCONNECT_DATATYPE_STRINGV) {
|
||||
DWORD cbString;
|
||||
char *pOutString;
|
||||
|
||||
HRESULT hr = SimConnect_RetrieveString(pSimData, cbData, reinterpret_cast<BYTE*>(pData), &pOutString, &cbString);
|
||||
|
||||
output[datumName] = std::make_pair(
|
||||
DatumType::Text,
|
||||
std::make_shared<std::string>(SUCCEEDED(hr) ? pOutString : "")
|
||||
);
|
||||
|
||||
datumSize = cbString;
|
||||
} else {
|
||||
|
||||
datumSize = sizeMap[datumType];
|
||||
|
||||
switch (datumType) {
|
||||
case SIMCONNECT_DATATYPE_INT32: {
|
||||
auto value = std::make_shared<int32_t>(*(int32_t*)pData);
|
||||
output[datumName] = std::make_pair(DatumType::Int32, value);
|
||||
}
|
||||
break;
|
||||
case SIMCONNECT_DATATYPE_INT64: {
|
||||
auto value = std::make_shared<int64_t>(*(int64_t*)pData);
|
||||
output[datumName] = std::make_pair(DatumType::Int64, value);
|
||||
}
|
||||
break;
|
||||
case SIMCONNECT_DATATYPE_FLOAT32: {
|
||||
auto value = std::make_shared<float>(*(float*)pData);
|
||||
output[datumName] = std::make_pair(DatumType::Float, value);
|
||||
}
|
||||
break;
|
||||
case SIMCONNECT_DATATYPE_FLOAT64: {
|
||||
auto value = std::make_shared<double>(*(double*)pData);
|
||||
output[datumName] = std::make_pair(DatumType::Double, value);
|
||||
}
|
||||
break;
|
||||
case SIMCONNECT_DATATYPE_STRING8:
|
||||
case SIMCONNECT_DATATYPE_STRING32:
|
||||
case SIMCONNECT_DATATYPE_STRING64:
|
||||
case SIMCONNECT_DATATYPE_STRING128:
|
||||
case SIMCONNECT_DATATYPE_STRING256:
|
||||
case SIMCONNECT_DATATYPE_STRING260: {
|
||||
auto value = std::make_shared< uint8_t>(*(const uint8_t*)pData);
|
||||
output[datumName] = std::make_pair(DatumType::Text, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
dataValueOffset += datumSize;
|
||||
}
|
||||
return std::make_shared<SimobjectDataBatch>(SimobjectDataBatch{
|
||||
pObjData->dwRequestID,
|
||||
output
|
||||
});
|
||||
}
|
||||
|
||||
DataBatchDefinition SimConnectSession::generateDataDefinition(std::vector<DatumRequest> datumRequests) {
|
||||
std::vector<std::string> requestedDatumNames;
|
||||
std::vector<SIMCONNECT_DATATYPE> requestedDatumTypes;
|
||||
|
||||
for (auto &datumRequest : datumRequests) {
|
||||
auto datumName = datumRequest.datumName.c_str();
|
||||
auto unitsName = datumRequest.unitName.has_value() ? datumRequest.unitName.value().c_str() : nullptr;
|
||||
auto datumType = SIMCONNECT_DATATYPE(datumRequest.datumType.value_or(SIMCONNECT_DATATYPE_FLOAT64));
|
||||
|
||||
HRESULT hr = SimConnect_AddToDataDefinition(
|
||||
hSimConnect,
|
||||
nextDataDefinitionId,
|
||||
datumName,
|
||||
unitsName,
|
||||
datumType
|
||||
);
|
||||
|
||||
check(hr);
|
||||
|
||||
requestedDatumNames.push_back(datumName);
|
||||
requestedDatumTypes.push_back(datumType);
|
||||
}
|
||||
|
||||
return {
|
||||
nextDataDefinitionId++,
|
||||
datumRequests.size(),
|
||||
requestedDatumNames,
|
||||
requestedDatumTypes
|
||||
};
|
||||
}
|
||||
|
||||
bool SimConnectSession::close() {
|
||||
HRESULT hr = SimConnect_Close(hSimConnect);
|
||||
check(hr);
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
void SimConnectSession::handleError(const std::string& name, NTSTATUS code) {
|
||||
char errorCodeBuffer[32];
|
||||
sprintf(errorCodeBuffer, "0x%08X", code); // Typically 0xC000014B, 0xC000020D or 0xC000013C
|
||||
|
||||
std::string errorCode(errorCodeBuffer);
|
||||
std::string errorMessage = "An error occured in " + name + ", NTSTATUS: " + errorCode;
|
||||
|
||||
std::cout << errorMessage.c_str() << std::endl;
|
||||
|
||||
if (fatalError == nullptr) {
|
||||
fatalError = std::make_shared<ErrorInfo>(ErrorInfo{errorCode, errorMessage});
|
||||
}
|
||||
}
|
||||
65
src/simconnect_session.h
Normal file
65
src/simconnect_session.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef SIMCONNECT_SESSION_H
|
||||
#define SIMCONNECT_SESSION_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <windows.h>
|
||||
|
||||
#include "commons.h"
|
||||
|
||||
struct SIMCONNECT_RECV;
|
||||
struct DataBatchDefinition;
|
||||
|
||||
class SimConnectSession {
|
||||
|
||||
public:
|
||||
SimConnectSession();
|
||||
bool open(const std::string& appName);
|
||||
bool close();
|
||||
|
||||
DispatchContent NextDispatch();
|
||||
|
||||
unsigned int subscribeToSystemEvent(const std::string& eventName);
|
||||
|
||||
unsigned int requestDataOnSimObject(std::vector<DatumRequest> datumRequests, unsigned int objectId, unsigned int period, unsigned int flags);
|
||||
unsigned int requestDataOnSimObject(unsigned int existingDataDefinitionId, unsigned int objectId, unsigned int period, unsigned int flags);
|
||||
|
||||
unsigned int requestDataOnSimObjectType(std::vector<DatumRequest> datumRequests, unsigned int radius, unsigned int simobjectType);
|
||||
unsigned int requestDataOnSimObjectType(unsigned int existingDataDefinitionId, unsigned int radius, unsigned int simobjectType);
|
||||
|
||||
unsigned int setDataOnSimObject(std::string datumName, std::string unitsName, double value);
|
||||
|
||||
unsigned int setAircraftInitialPosition(
|
||||
double lat,
|
||||
double lng,
|
||||
double altitude,
|
||||
double pitch,
|
||||
double bank,
|
||||
double heading,
|
||||
bool onGround,
|
||||
unsigned long airspeed
|
||||
);
|
||||
unsigned int requestSystemState(std::string stateName);
|
||||
unsigned int flightLoad(std::string fileName);
|
||||
unsigned int transmitClientEvent(std::string eventName, unsigned int objectId, int data);
|
||||
unsigned int createDataDefinition(std::vector<DatumRequest> datumRequests);
|
||||
|
||||
private:
|
||||
HANDLE hSimConnect;
|
||||
std::shared_ptr<ErrorInfo> fatalError;
|
||||
|
||||
DispatchContent process(SIMCONNECT_RECV* pData, DWORD cbData);
|
||||
void handleError(const std::string& name, NTSTATUS code);
|
||||
|
||||
std::shared_ptr<ExceptionInfo> getExceptionInfo(SIMCONNECT_RECV* pData);
|
||||
std::shared_ptr<SimEvent> getEvent(SIMCONNECT_RECV* pData);
|
||||
std::shared_ptr<SimInfo> getSimInfo(SIMCONNECT_RECV* pData);
|
||||
std::shared_ptr<SimSystemState> getSystemState(SIMCONNECT_RECV* pData);
|
||||
std::shared_ptr<SimobjectDataBatch> getSimObjectData(SIMCONNECT_RECV* pData, DWORD cbData);
|
||||
DataBatchDefinition generateDataDefinition(std::vector<DatumRequest> datumRequests);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user