├── .flake8 ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── doc ├── sc-get.png ├── sc-install-completion.png ├── sc-search.png ├── sc-send.png ├── sc-set.png ├── sc-tab-completion.png └── sc-watch.png ├── examples ├── README.md ├── call_dispatch.py ├── demo.py ├── monitor_metrics.py ├── send_event.py ├── set_data.py ├── show_version.py ├── subscribe.py └── test_units.py ├── pyproject.toml ├── scripts ├── SimConnect.h ├── SimConnect_cpp.h ├── float.h ├── genscdefs.py ├── mkidx.py ├── prepvars.py └── scrapevars.py ├── setup.cfg └── simconnect ├── SimConnect.dll ├── __init__.py ├── _typerpatch.py ├── changedict.py ├── cli.py ├── datadef.py ├── receiver.py ├── sc.py ├── scdefs.py ├── scvars.json ├── scvars.py ├── scvars_idx.json └── winstubs.py /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | pysimconnect.egg-info/ 3 | dist/ 4 | scripts/all_units.json 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 The Python Packaging Authority 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include scripts/* 2 | include simconnect/scvars.json 3 | include simconnect/SimConnect.dll 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The `pysimconnect` package provides a simple, efficient wrapper for FlightSimulator 2020's 2 | [SimConnect SDK](https://docs.flightsimulator.com/html/index.htm?#t=Programming_Tools%2FSimConnect%2FSimConnect_SDK.htm), 3 | inspired by [Python-SimConnect](https://github.com/odwdinc/Python-SimConnect). 4 | 5 | If you're looking to build external instrument displays, 6 | connect custom controllers to FS2020, 7 | or just explore how the simulation works in more detail 8 | then `pysimconnect` is for you. 9 | You might also be interested in [G3](https://github.com/patricksurry/g3), 10 | a flexible Javascript framework for building steam gauge instrument panels. 11 | 12 | The package contains a python module called `simconnect` 13 | which exposes a simple pythonic interface 14 | to read simulator variables, 15 | set editable variables, 16 | subscribe to variable changes, 17 | and trigger simulator events. 18 | It also exposes all of the low-level SDK methods, 19 | constants and enumerations from the `SimConnect.h` 20 | SDK API based on a simple automated translation 21 | from the C++ definitions to Python equivalents. 22 | 23 | The package also offers a `simconnect` command-line tool 24 | which lets you search for 25 | variables, events and measurement units from the SDK documentation; 26 | inspect, change or watch variables over time; 27 | and send simulator events, 28 | all without writing any code. 29 | 30 | 31 | Quick start 32 | --- 33 | 34 | Making sure you're using python 3.6+ and install the package: 35 | 36 | pip install pysimconnect 37 | 38 | To use the `simconnect` command-line tool, 39 | install [Powershell7](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2) and 40 | set your [default terminal](https://devblogs.microsoft.com/commandline/windows-terminal-as-your-default-command-line-experience/) 41 | to Windows Terminal rather than Windows Console Host. 42 | Start Powershell7 and install TAB auto-completion support by typing 43 | `simconnect --install-completion powershell` 44 | then restart your terminal as instructed: 45 | 46 | ![simconnect install completion](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-install-completion.png) 47 | 48 | Now start a flight in FS2020, perhaps with the AI pilot flying. 49 | Let's experiment with reading and modifying the altitude. 50 | First let's find some relevant variables with `search`: 51 | 52 | ![simconnect search example](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-search.png) 53 | 54 | Nice! We get a list of results from the SDK documentation ranked by relevance. 55 | Result categories are distinguished by different colors and symbols, e.g. 56 | variables 🧭, events ⚙️ and units 📐, with a ✏️ marking variables which we can change. 57 | 58 | Now let's read the value of the `PLANE ALTITUDE` variable using the `get` command. 59 | Start typing `simconnect get PLA`, hitting the TAB key part way through the variable name 60 | to see contextual auto-complete options: 61 | 62 | ![simconnect tab completion](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-tab-completion.png) 63 | 64 | Select the desired `PLANE_ALTITUDE` option and hit ENTER: 65 | 66 | ![simconnect get example](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-get.png) 67 | 68 | Note that although the underlying SDK variables are space-separated 69 | and events are underscore-separated, 70 | the command-line tool recognizes either version. 71 | Normally using underscore-separated everywhere will be easier for auto-completion 72 | and avoids quoting in the terminal. 73 | 74 | We can read multiple variables by just appending them in a list. 75 | We can also monitor multiple variables over time using `watch`: 76 | 77 | ![simconnect watch example](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-watch.png) 78 | 79 | By default we'll see an update once every second, 80 | highlighting the variables that change during each update. 81 | Some commands support additional options, 82 | for example `simconnect watch --help` will show us how to change the 83 | monitoring interval time. 84 | For general help, try `simconnect --help`. 85 | 86 | Now let's change the plane's altitude during flight(!) using the `set` command. 87 | Here we'll add the `--units` option to specify that our value is measured in `meters` rather 88 | than the default `feet`: 89 | 90 | ![simconnect set example](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-set.png) 91 | 92 | Lastly, let's send an event to FS2020. 93 | A simple example is to bump the altimeter adjustment knob, like so. 94 | If you send this event a few times, you'll see the indicated altitude adjust in response. 95 | 96 | ![simconnect send example](https://raw.githubusercontent.com/patricksurry/pysimconnect/master/doc/sc-send.png) 97 | 98 | This simple event needs no data, but with others you also need to provide a value. 99 | 100 | 101 | Working with python 102 | --- 103 | 104 | The command-line tool is just a lightweight 105 | wrapper for some features of the `simconnect` python package. 106 | This means that you can write simple python code to do anything 107 | the command-line tool does, and much more besides. 108 | The best way to get started is to browse some [examples](examples/README.md) 109 | which show both low-level interaction with the SDK, 110 | and some of the simplified sugar the package offers. 111 | 112 | 113 | With so many moving parts, debugging errors can sometimes be tricky. 114 | One useful tool is to set the `LOGLEVEL` environment variable 115 | to `DEBUG` before running your code, rather than the default `INFO`: 116 | 117 | set LOGLEVEL=DEBUG 118 | 119 | Also, be warned that the official 120 | [SDK documentation](https://docs.flightsimulator.com/html/index.htm?#t=Programming_Tools%2FSimConnect%2FSimConnect_SDK.htm_) 121 | has various errors (copy/paste gone wrong?) 122 | which can make it difficult to understand some details. 123 | Where possible refer directly to the `SimConnect.h` 124 | header file definitions and comments 125 | as a more authoritative source. 126 | 127 | 128 | What's what? 129 | --- 130 | 131 | Find the full source on github at https://github.com/patricksurry/pysimconnect. 132 | The `simconnect` folder contains the package itself. 133 | 134 | The main interface is defined in `sc.py` which wraps the raw 135 | definitions from the auto-generated `scdefs.py`, 136 | providing access to both the low-level 137 | SDK functions as well as some pythonic sugar. 138 | The command line tool is implemented by `cli.py`. 139 | 140 | The package requires a copy of `SimConnect.dll` to work. 141 | This normally ships with FS2020 but a recent copy is also included here. 142 | You can point to your own version by specifying the `dll_path` argument 143 | when initializing `SimConnect(...)`. 144 | The `scvars.json` file lists all the simulation variables (SimVars), 145 | events and dimensional units, which were scraped from the SDK documentation pages 146 | using `scripts/scrapevars.json`. This is useful for finding content 147 | you want to interact with, inferring missing units and data-types 148 | when querying simulation variables, and sanity-checking variable names. 149 | 150 | The `examples` folder contains various illustrations of how to use 151 | the package, showing both low-level SDK access and the pythonic wrappers. 152 | See the `README.md` there for more details. 153 | 154 | The `scripts` folder includes several scripts used to generate 155 | parts of the package. 156 | The `genscdefs.py` script creates `scdefs.py` from a post-processed 157 | version of the `SimConnect.h` C++ header that ships with the SDK 158 | (which can be installed via the Options > General > Developer tools help menu). 159 | This generates a python translation of all the SDK function declarations, data structures 160 | and enumerated constants. The automated translation is quite fragile: 161 | it assumes the header is formatted in a particular way, and has been 162 | pre-processed with `cpp` to `SimConnect_cpp.h` from the raw header. 163 | This approach makes it easy to tweak the rules for mapping from C++ 164 | to Python, as long as header format doesn't change significantly. 165 | 166 | 167 | 168 | Packaging and distribution 169 | --- 170 | 171 | Bump version in `setup.cfg` then following https://packaging.python.org/en/latest/tutorials/packaging-projects/ 172 | 173 | python3 -m build 174 | git commit -am ... 175 | git push origin 176 | git tag v0.2.6 177 | git push origin --tags 178 | python3 -m twine upload dist/*0.2.6* 179 | # login with username: __token__ / password: pypi-... 180 | 181 | -------------------------------------------------------------------------------- /doc/sc-get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-get.png -------------------------------------------------------------------------------- /doc/sc-install-completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-install-completion.png -------------------------------------------------------------------------------- /doc/sc-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-search.png -------------------------------------------------------------------------------- /doc/sc-send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-send.png -------------------------------------------------------------------------------- /doc/sc-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-set.png -------------------------------------------------------------------------------- /doc/sc-tab-completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-tab-completion.png -------------------------------------------------------------------------------- /doc/sc-watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/doc/sc-watch.png -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | Introductory examples of how to use the `simconnect` package. 2 | 3 | - `demo.py`: illustrates all major features 4 | 5 | - `test_units.py`: illustrate SDK unit conversion options 6 | 7 | - `send_event.py`: simple send_event example 8 | 9 | - `set_data.py`: simple set_datum example 10 | 11 | - `subscribe.py`: pythonic wrapper for watching one or more variables over time 12 | (cf. `monitor_metrics.py` for a low-level implementation) 13 | 14 | Examples calling SDK functions directly: 15 | 16 | - `show_version.py`: trivial low-level example showing how to retrieve the result of the SDK `Open()` call. 17 | 18 | - `call_dispatch.py`: example of how to poll for results with a callback function, 19 | which is only called when a message is available 20 | 21 | - `monitor_metrics.py`: example of several low-level SDK calls to retrieve a group of simulation variables 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/call_dispatch.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect, DispatchProc, ReceiverInstance 2 | from time import sleep 3 | 4 | 5 | """ 6 | Illlustrate low-level use of DispatchProc via CallDispatch 7 | In this case the call to CallDispatch will always succeed, 8 | but will only trigger the dispatcher when a message is ready. 9 | 10 | Compare GetNextDispatch which will raises an error when no message is waiting, 11 | but can still be used for polling until it succeeds 12 | """ 13 | 14 | 15 | def dispatcher(pRecv, nSize, pContext): 16 | """eventually called once when the result of the implicit Open() call is ready""" 17 | recv = ReceiverInstance.cast_recv(pRecv) 18 | print(f"dispatcher: received {recv.__class__.__name__} with size {nSize} and context {pContext}") 19 | 20 | 21 | # disable the default receivers so we can see the RECV_OPEN response 22 | with SimConnect(name='CallDispatch', default_receivers=[]) as sc: 23 | for _ in range(10): 24 | print('CallDispatch') 25 | sc.CallDispatch(DispatchProc(dispatcher), None) 26 | sleep(0.1) 27 | -------------------------------------------------------------------------------- /examples/demo.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from simconnect import SimConnect, PERIOD_VISUAL_FRAME 3 | 4 | # open a connection to the SDK 5 | # or use as a context via `with SimConnect() as sc: ... ` 6 | sc = SimConnect() 7 | 8 | # one-off blocking fetch of a single simulator variable, 9 | # which will wait up to 1s (default) to receive the value 10 | altitude = sc.get_simdatum("Indicated Altitude") 11 | print("Got indicated altitude", altitude) 12 | 13 | # subscribing to one or more variables is much more efficient, 14 | # with the SDK sending updated values up to once per simulator frame. 15 | # the variables are tracked in `datadef.simdata` 16 | # which is a dictionary that tracks the last modified time 17 | # of each variable. changes can also trigger an optional callback function 18 | datadef = sc.subscribe_simdata( 19 | [ 20 | "Indicated Altitude", 21 | dict(name="Kohlsman setting hg", units="hectopascal"), 22 | "ELECTRICAL BATTERY BUS VOLTAGE" 23 | ], 24 | # request an update every ten rendered frames 25 | period=PERIOD_VISUAL_FRAME, 26 | interval=10, 27 | ) 28 | print("Inferred variable units", datadef.get_units()) 29 | 30 | # track the most recent data update 31 | latest = datadef.simdata.latest() 32 | 33 | for i in range(10): 34 | # bump altitude, which is a settable simulator variable 35 | sc.set_simdatum("Indicated Altitude", altitude + 100) 36 | 37 | # trigger an event that increments the barometer setting 38 | # some events also take an optional data value 39 | sc.send_event("KOHLSMAN_INC") 40 | 41 | # wait a bit... 42 | sleep(0.5) 43 | 44 | # pump the SDK event queue to deal with any recent messages 45 | while sc.receive(): 46 | pass 47 | 48 | # show data that's been changed since the last update 49 | print(f"Updated data {datadef.simdata.changedsince(latest)}") 50 | 51 | latest = datadef.simdata.latest() 52 | 53 | # fetch the current altitude 54 | altitude = datadef.simdata['Indicated Altitude'] 55 | 56 | # explicity close the SDK connection 57 | sc.Close() 58 | -------------------------------------------------------------------------------- /examples/monitor_metrics.py: -------------------------------------------------------------------------------- 1 | from simconnect import ( 2 | SimConnect, ReceiverInstance, OBJECT_ID_USER, 3 | PERIOD_SECOND, DATA_REQUEST_FLAG_CHANGED, DATA_REQUEST_FLAG_TAGGED, 4 | DATATYPE_FLOAT64, RECV_SIMOBJECT_DATA, RECV_EXCEPTION, RECV_P 5 | ) 6 | from ctypes import byref, sizeof, cast, POINTER, c_double 7 | from ctypes.wintypes import DWORD 8 | from time import sleep 9 | 10 | 11 | """ 12 | Low level example showing the flow for watching a group of simulation variables. 13 | Compare subscribe.py for a more pythonic version 14 | """ 15 | with SimConnect(name='MonitorMetrics') as sc: 16 | def_id = 0x1234 17 | simvars = [ 18 | ("Kohlsman setting hg", "inHg"), 19 | ("Indicated Altitude", "feet"), 20 | ("Plane Latitude", "degrees"), 21 | ("Plane Longitude", "degrees"), 22 | ] 23 | for i, (simvar, unit) in enumerate(simvars): 24 | sc.AddToDataDefinition(def_id, simvar, unit, DATATYPE_FLOAT64, 0, i) 25 | 26 | req_id = 0xfeed 27 | sc.RequestDataOnSimObject( 28 | req_id, # request identifier for response packets 29 | def_id, # the data definition group 30 | OBJECT_ID_USER, 31 | PERIOD_SECOND, 32 | DATA_REQUEST_FLAG_CHANGED | DATA_REQUEST_FLAG_TAGGED, 33 | 0, # number of periods before starting events 34 | 1, # number of periods between events, e.g. with PERIOD_SIM_FRAME 35 | 0, # number of repeats, 0 is forever 36 | ) 37 | pRecv = RECV_P() 38 | nSize = DWORD() 39 | while True: 40 | try: 41 | print('Trying') 42 | sc.GetNextDispatch(byref(pRecv), byref(nSize)) 43 | except OSError: 44 | sleep(0.5) 45 | continue 46 | recv = ReceiverInstance.cast_recv(pRecv) 47 | print(f"got {recv.__class__.__name__}") 48 | if isinstance(recv, RECV_EXCEPTION): 49 | print(f"Got exception {recv.dwException}, sendID {recv.dwSendID}, index {recv.dwIndex}") 50 | elif isinstance(recv, RECV_SIMOBJECT_DATA): 51 | print(f"Received SIMOBJECT_DATA with {recv.dwDefineCount} data elements, flags {recv.dwFlags}") 52 | if recv.dwRequestID == req_id: 53 | print(f"Matched request 0x{req_id:X}") 54 | data = {} 55 | # see datadef.py add_receiver() for the general case 56 | # dwData is a placeholder for start of actual data 57 | offset = RECV_SIMOBJECT_DATA.dwData.offset 58 | for _ in range(recv.dwDefineCount): 59 | idx = cast(byref(recv, offset), POINTER(DWORD))[0] 60 | offset += sizeof(DWORD) 61 | # DATATYPE_FLOAT64 => c_double 62 | val = cast(byref(recv, offset), POINTER(c_double))[0] 63 | offset += sizeof(c_double) 64 | name = simvars[idx][0] 65 | data[name] = val 66 | print(f"Received simvars {data}") 67 | -------------------------------------------------------------------------------- /examples/send_event.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect 2 | 3 | 4 | with SimConnect(name='SendEvent') as sc: 5 | # click up the altimeter setting a few times 6 | event = 'KOHLSMAN_INC' 7 | for _ in range(10): 8 | print(f"Sending {event} event") 9 | # some events require an optional `data` field here, see SDK doc 10 | sc.send_event(event) 11 | 12 | for _ in range(10): 13 | # pump the event queue a few times to see what comes back... 14 | result = sc.receive(timeout_seconds=0.2) 15 | print(f"Received? {result}") 16 | -------------------------------------------------------------------------------- /examples/set_data.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect 2 | from time import sleep 3 | 4 | 5 | """Simple example of setting a simvar""" 6 | with SimConnect(name='GainAltitude') as sc: 7 | for _ in range(10): 8 | altitude = sc.get_simdatum('Indicated Altitude') 9 | print(f"Got altitude {altitude}, adding 100") 10 | altitude += 100 11 | sc.set_simdatum('Indicated Altitude', altitude) 12 | sleep(0.5) 13 | -------------------------------------------------------------------------------- /examples/show_version.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect, RECV_P, ReceiverInstance 2 | from ctypes import byref 3 | from ctypes.wintypes import DWORD 4 | from time import sleep 5 | 6 | 7 | """ 8 | Use a SimConnect object as a context manager, 9 | removing the default receiver handlers so we can 10 | manually retrieve the response to the implicit SimConnect.Open() 11 | which is a RECV_OPEN struct containing various version numbers. 12 | Compare receiver.receiveOpen which normally logs this data automatically 13 | """ 14 | with SimConnect(name='ShowVersion', default_receivers=[]) as sc: 15 | sleep(0.5) # make sure the response is waiting for us 16 | pRecv = RECV_P() 17 | nSize = DWORD() 18 | sc.GetNextDispatch(byref(pRecv), byref(nSize)) 19 | ro = ReceiverInstance.cast_recv(pRecv) 20 | appVer = f"v{ro.dwApplicationVersionMajor}.{ro.dwApplicationVersionMinor}" 21 | appBuild = f"build {ro.dwApplicationBuildMajor}.{ro.dwApplicationBuildMinor}" 22 | scVer = f"v{ro.dwSimConnectVersionMajor}.{ro.dwSimConnectVersionMinor}" 23 | scBuild = f"build {ro.dwSimConnectBuildMajor}.{ro.dwSimConnectBuildMinor}" 24 | print(f"{ro.__class__.__name__} App: {ro.szApplicationName} {appVer} {appBuild} SimConnect: {scVer} {scBuild}") 25 | -------------------------------------------------------------------------------- /examples/subscribe.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect 2 | 3 | """Simple example of subscribing to a set of metrics""" 4 | 5 | with SimConnect(name='MonitorMetrics') as sc: 6 | simvars = [ 7 | # We can monitor simvars with string values 8 | "ATC ID", 9 | # boolean, flag, and mask vars are retured as int, most others as float 10 | "ATC cleared landing", 11 | # Simulation variable names are not case-sensitive 12 | "Kohlsman setting hg:1", 13 | # Provide a dictionary to specify optional attributes: 14 | # 'units' (per SDK), 'epsilon' (default 1e-4) and 'type' (default DATATYPE_FLOAT64) 15 | dict(name="Indicated Altitude", units="m", epsilon=0.1), 16 | dict(name="Plane Latitude", units='degrees'), 17 | dict(name="Plane Longitude", units='degrees'), 18 | ] 19 | 20 | print(f"One-off snaphsot of {sc.get_simdata(simvars[0])}") 21 | 22 | # but subscribe is more efficient if we're repeating... 23 | dd = sc.subscribe_simdata(simvars) 24 | print(f"Subscribed to simvars with units {dd.get_units()}") 25 | 26 | latest = 0 27 | while True: 28 | while sc.receive(timeout_seconds=0.1): 29 | # clear queue of pending results, processed by receiver handlers 30 | print('received result') 31 | pass 32 | n = len(dd.simdata.changedsince(latest)) 33 | if n: 34 | print(f"Updated {n} simvars") 35 | print(dd.simdata) 36 | latest = dd.simdata.latest() 37 | -------------------------------------------------------------------------------- /examples/test_units.py: -------------------------------------------------------------------------------- 1 | from simconnect import SimConnect 2 | 3 | # The SDK will automatically convert simulation variables to compatible units 4 | 5 | with SimConnect() as sc: 6 | print("Fetching Indicated Altitude with various units") 7 | print("default (Feet inferred)", sc.get_simdatum("Indicated Altitude")) 8 | # These are defined explicitly as units by the SDK 9 | print("Feet", sc.get_simdatum("Indicated Altitude", units="Feet")) 10 | print("Foot", sc.get_simdatum("Indicated Altitude", units="Foot")) 11 | # Case insensitive? 12 | print("feet", sc.get_simdatum("Indicated Altitude", units="feet")) 13 | print("FEET", sc.get_simdatum("Indicated Altitude", units="FEET")) 14 | # Alternative length units 15 | print("meters", sc.get_simdatum("Indicated Altitude", units="meters")) 16 | print("m", sc.get_simdatum("Indicated Altitude", units="m")) 17 | # Explicitly empty, oddly seems to default to meters 18 | print("empty ('')", sc.get_simdatum("Indicated Altitude", units="")) 19 | # fails to retrieve data, returns None with warning 20 | print("FUBAR (unknown)", sc.get_simdatum("Indicated Altitude", units="FUBAR")) -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel" 5 | ] 6 | build-backend = "setuptools.build_meta" 7 | -------------------------------------------------------------------------------- /scripts/SimConnect.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All Rights Reserved. 4 | // 5 | //----------------------------------------------------------------------------- 6 | 7 | #ifndef _SIMCONNECT_H_ 8 | #define _SIMCONNECT_H_ 9 | 10 | #pragma once 11 | 12 | #ifdef _MSFS_WASM 13 | #ifndef SIMCONNECT_WASM_MODULE 14 | #define SIMCONNECT_WASM_MODULE "env" 15 | #endif 16 | #endif 17 | 18 | #ifndef DWORD_MAX 19 | #define DWORD_MAX 0xFFFFFFFF 20 | #endif 21 | 22 | #include 23 | 24 | typedef DWORD SIMCONNECT_OBJECT_ID; 25 | 26 | //---------------------------------------------------------------------------- 27 | // Constants 28 | //---------------------------------------------------------------------------- 29 | 30 | static const DWORD SIMCONNECT_UNUSED = DWORD_MAX; // special value to indicate unused event, ID 31 | static const DWORD SIMCONNECT_OBJECT_ID_USER = 0; // proxy value for User vehicle ObjectID 32 | 33 | static const float SIMCONNECT_CAMERA_IGNORE_FIELD = FLT_MAX; //Used to tell the Camera API to NOT modify the value in this part of the argument. 34 | 35 | static const DWORD SIMCONNECT_CLIENTDATA_MAX_SIZE = 8192; // maximum value for SimConnect_CreateClientData dwSize parameter 36 | 37 | 38 | // Notification Group priority values 39 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority 40 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000; // highest priority that allows events to be masked 41 | static const DWORD SIMCONNECT_GROUP_PRIORITY_STANDARD = 1900000000; // standard priority 42 | static const DWORD SIMCONNECT_GROUP_PRIORITY_DEFAULT = 2000000000; // default priority 43 | static const DWORD SIMCONNECT_GROUP_PRIORITY_LOWEST = 4000000000; // priorities lower than this will be ignored 44 | 45 | //Weather observations Metar strings 46 | static const DWORD MAX_METAR_LENGTH = 2000; 47 | 48 | // Maximum thermal size is 100 km. 49 | static const float MAX_THERMAL_SIZE = 100000; 50 | static const float MAX_THERMAL_RATE = 1000; 51 | 52 | // SIMCONNECT_DATA_INITPOSITION.Airspeed 53 | static const DWORD INITPOSITION_AIRSPEED_CRUISE = -1; // aircraft's cruise airspeed 54 | static const DWORD INITPOSITION_AIRSPEED_KEEP = -2; // keep current airspeed 55 | 56 | // AddToClientDataDefinition dwSizeOrType parameter type values 57 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT8 = -1; // 8-bit integer number 58 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT16 = -2; // 16-bit integer number 59 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT32 = -3; // 32-bit integer number 60 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT64 = -4; // 64-bit integer number 61 | static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT32 = -5; // 32-bit floating-point number (float) 62 | static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT64 = -6; // 64-bit floating-point number (double) 63 | 64 | // AddToClientDataDefinition dwOffset parameter special values 65 | static const DWORD SIMCONNECT_CLIENTDATAOFFSET_AUTO = -1; // automatically compute offset of the ClientData variable 66 | 67 | // Open ConfigIndex parameter special value 68 | static const DWORD SIMCONNECT_OPEN_CONFIGINDEX_LOCAL = -1; // ignore SimConnect.cfg settings, and force local connection 69 | 70 | //---------------------------------------------------------------------------- 71 | // Enum definitions 72 | //---------------------------------------------------------------------------- 73 | 74 | //these came from substituteMacros 75 | #define SIMCONNECT_REFSTRUCT struct 76 | #define SIMCONNECT_STRUCT struct 77 | #define SIMCONNECT_STRING(name, size) char name[size] 78 | #define SIMCONNECT_GUID GUID 79 | #define SIMCONNECT_STRINGV(name) char name[1] 80 | #define SIMCONNECT_DATAV(name, id, count) DWORD name 81 | #define SIMCONNECT_FIXEDTYPE_DATAV(type, name, count, cliMarshalAs, cliType) type name[1] 82 | #define SIMCONNECT_GUID GUID 83 | #define SIMCONNECT_ENUM enum 84 | #define SIMCONNECT_ENUM_FLAGS typedef DWORD 85 | #define SIMCONNECT_USER_ENUM typedef DWORD 86 | 87 | 88 | // Receive data types 89 | SIMCONNECT_ENUM SIMCONNECT_RECV_ID { 90 | SIMCONNECT_RECV_ID_NULL, 91 | SIMCONNECT_RECV_ID_EXCEPTION, 92 | SIMCONNECT_RECV_ID_OPEN, 93 | SIMCONNECT_RECV_ID_QUIT, 94 | SIMCONNECT_RECV_ID_EVENT, 95 | SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE, 96 | SIMCONNECT_RECV_ID_EVENT_FILENAME, 97 | SIMCONNECT_RECV_ID_EVENT_FRAME, 98 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA, 99 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE, 100 | SIMCONNECT_RECV_ID_WEATHER_OBSERVATION, 101 | SIMCONNECT_RECV_ID_CLOUD_STATE, 102 | SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID, 103 | SIMCONNECT_RECV_ID_RESERVED_KEY, 104 | SIMCONNECT_RECV_ID_CUSTOM_ACTION, 105 | SIMCONNECT_RECV_ID_SYSTEM_STATE, 106 | SIMCONNECT_RECV_ID_CLIENT_DATA, 107 | SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE, 108 | SIMCONNECT_RECV_ID_AIRPORT_LIST, 109 | SIMCONNECT_RECV_ID_VOR_LIST, 110 | SIMCONNECT_RECV_ID_NDB_LIST, 111 | SIMCONNECT_RECV_ID_WAYPOINT_LIST, 112 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED, 113 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED, 114 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED, 115 | SIMCONNECT_RECV_ID_EVENT_RACE_END, 116 | SIMCONNECT_RECV_ID_EVENT_RACE_LAP, 117 | #ifdef ENABLE_SIMCONNECT_EXPERIMENTAL 118 | SIMCONNECT_RECV_ID_PICK, 119 | #endif //ENABLE_SIMCONNECT_EXPERIMENTAL 120 | }; 121 | 122 | 123 | 124 | // Data data types 125 | SIMCONNECT_ENUM SIMCONNECT_DATATYPE { 126 | SIMCONNECT_DATATYPE_INVALID, // invalid data type 127 | SIMCONNECT_DATATYPE_INT32, // 32-bit integer number 128 | SIMCONNECT_DATATYPE_INT64, // 64-bit integer number 129 | SIMCONNECT_DATATYPE_FLOAT32, // 32-bit floating-point number (float) 130 | SIMCONNECT_DATATYPE_FLOAT64, // 64-bit floating-point number (double) 131 | SIMCONNECT_DATATYPE_STRING8, // 8-byte string 132 | SIMCONNECT_DATATYPE_STRING32, // 32-byte string 133 | SIMCONNECT_DATATYPE_STRING64, // 64-byte string 134 | SIMCONNECT_DATATYPE_STRING128, // 128-byte string 135 | SIMCONNECT_DATATYPE_STRING256, // 256-byte string 136 | SIMCONNECT_DATATYPE_STRING260, // 260-byte string 137 | SIMCONNECT_DATATYPE_STRINGV, // variable-length string 138 | 139 | SIMCONNECT_DATATYPE_INITPOSITION, // see SIMCONNECT_DATA_INITPOSITION 140 | SIMCONNECT_DATATYPE_MARKERSTATE, // see SIMCONNECT_DATA_MARKERSTATE 141 | SIMCONNECT_DATATYPE_WAYPOINT, // see SIMCONNECT_DATA_WAYPOINT 142 | SIMCONNECT_DATATYPE_LATLONALT, // see SIMCONNECT_DATA_LATLONALT 143 | SIMCONNECT_DATATYPE_XYZ, // see SIMCONNECT_DATA_XYZ 144 | 145 | SIMCONNECT_DATATYPE_MAX // enum limit 146 | }; 147 | 148 | // Exception error types 149 | SIMCONNECT_ENUM SIMCONNECT_EXCEPTION { 150 | SIMCONNECT_EXCEPTION_NONE, 151 | 152 | SIMCONNECT_EXCEPTION_ERROR, 153 | SIMCONNECT_EXCEPTION_SIZE_MISMATCH, 154 | SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, 155 | SIMCONNECT_EXCEPTION_UNOPENED, 156 | SIMCONNECT_EXCEPTION_VERSION_MISMATCH, 157 | SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, 158 | SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, 159 | SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, 160 | SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, 161 | SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, 162 | SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, 163 | SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, 164 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, 165 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, 166 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, 167 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, 168 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, 169 | SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, 170 | SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, 171 | SIMCONNECT_EXCEPTION_DATA_ERROR, 172 | SIMCONNECT_EXCEPTION_INVALID_ARRAY, 173 | SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, 174 | SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED, 175 | SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, 176 | SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, 177 | SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, 178 | SIMCONNECT_EXCEPTION_INVALID_ENUM, 179 | SIMCONNECT_EXCEPTION_DEFINITION_ERROR, 180 | SIMCONNECT_EXCEPTION_DUPLICATE_ID, 181 | SIMCONNECT_EXCEPTION_DATUM_ID, 182 | SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, 183 | SIMCONNECT_EXCEPTION_ALREADY_CREATED, 184 | SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE, 185 | SIMCONNECT_EXCEPTION_OBJECT_CONTAINER, 186 | SIMCONNECT_EXCEPTION_OBJECT_AI, 187 | SIMCONNECT_EXCEPTION_OBJECT_ATC, 188 | SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE, 189 | }; 190 | 191 | // Object types 192 | SIMCONNECT_ENUM SIMCONNECT_SIMOBJECT_TYPE { 193 | SIMCONNECT_SIMOBJECT_TYPE_USER, 194 | SIMCONNECT_SIMOBJECT_TYPE_ALL, 195 | SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, 196 | SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER, 197 | SIMCONNECT_SIMOBJECT_TYPE_BOAT, 198 | SIMCONNECT_SIMOBJECT_TYPE_GROUND, 199 | }; 200 | 201 | // EventState values 202 | SIMCONNECT_ENUM SIMCONNECT_STATE { 203 | SIMCONNECT_STATE_OFF, 204 | SIMCONNECT_STATE_ON, 205 | }; 206 | 207 | // Object Data Request Period values 208 | SIMCONNECT_ENUM SIMCONNECT_PERIOD { 209 | SIMCONNECT_PERIOD_NEVER, 210 | SIMCONNECT_PERIOD_ONCE, 211 | SIMCONNECT_PERIOD_VISUAL_FRAME, 212 | SIMCONNECT_PERIOD_SIM_FRAME, 213 | SIMCONNECT_PERIOD_SECOND, 214 | }; 215 | 216 | 217 | SIMCONNECT_ENUM SIMCONNECT_MISSION_END { 218 | SIMCONNECT_MISSION_FAILED, 219 | SIMCONNECT_MISSION_CRASHED, 220 | SIMCONNECT_MISSION_SUCCEEDED 221 | }; 222 | 223 | // ClientData Request Period values 224 | SIMCONNECT_ENUM SIMCONNECT_CLIENT_DATA_PERIOD { 225 | SIMCONNECT_CLIENT_DATA_PERIOD_NEVER, 226 | SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, 227 | SIMCONNECT_CLIENT_DATA_PERIOD_VISUAL_FRAME, 228 | SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, 229 | SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, 230 | }; 231 | 232 | SIMCONNECT_ENUM SIMCONNECT_TEXT_TYPE { 233 | SIMCONNECT_TEXT_TYPE_SCROLL_BLACK, 234 | SIMCONNECT_TEXT_TYPE_SCROLL_WHITE, 235 | SIMCONNECT_TEXT_TYPE_SCROLL_RED, 236 | SIMCONNECT_TEXT_TYPE_SCROLL_GREEN, 237 | SIMCONNECT_TEXT_TYPE_SCROLL_BLUE, 238 | SIMCONNECT_TEXT_TYPE_SCROLL_YELLOW, 239 | SIMCONNECT_TEXT_TYPE_SCROLL_MAGENTA, 240 | SIMCONNECT_TEXT_TYPE_SCROLL_CYAN, 241 | SIMCONNECT_TEXT_TYPE_PRINT_BLACK=0x0100, 242 | SIMCONNECT_TEXT_TYPE_PRINT_WHITE, 243 | SIMCONNECT_TEXT_TYPE_PRINT_RED, 244 | SIMCONNECT_TEXT_TYPE_PRINT_GREEN, 245 | SIMCONNECT_TEXT_TYPE_PRINT_BLUE, 246 | SIMCONNECT_TEXT_TYPE_PRINT_YELLOW, 247 | SIMCONNECT_TEXT_TYPE_PRINT_MAGENTA, 248 | SIMCONNECT_TEXT_TYPE_PRINT_CYAN, 249 | SIMCONNECT_TEXT_TYPE_MENU=0x0200, 250 | }; 251 | 252 | SIMCONNECT_ENUM SIMCONNECT_TEXT_RESULT { 253 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_1, 254 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_2, 255 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_3, 256 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_4, 257 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_5, 258 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_6, 259 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_7, 260 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_8, 261 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_9, 262 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_10, 263 | SIMCONNECT_TEXT_RESULT_DISPLAYED = 0x00010000, 264 | SIMCONNECT_TEXT_RESULT_QUEUED, 265 | SIMCONNECT_TEXT_RESULT_REMOVED, 266 | SIMCONNECT_TEXT_RESULT_REPLACED, 267 | SIMCONNECT_TEXT_RESULT_TIMEOUT, 268 | }; 269 | 270 | SIMCONNECT_ENUM SIMCONNECT_WEATHER_MODE { 271 | SIMCONNECT_WEATHER_MODE_THEME, 272 | SIMCONNECT_WEATHER_MODE_RWW, 273 | SIMCONNECT_WEATHER_MODE_CUSTOM, 274 | SIMCONNECT_WEATHER_MODE_GLOBAL, 275 | }; 276 | 277 | SIMCONNECT_ENUM SIMCONNECT_FACILITY_LIST_TYPE { 278 | SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, 279 | SIMCONNECT_FACILITY_LIST_TYPE_WAYPOINT, 280 | SIMCONNECT_FACILITY_LIST_TYPE_NDB, 281 | SIMCONNECT_FACILITY_LIST_TYPE_VOR, 282 | SIMCONNECT_FACILITY_LIST_TYPE_COUNT // invalid 283 | }; 284 | 285 | 286 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_VOR_FLAGS; // flags for SIMCONNECT_RECV_ID_VOR_LIST 287 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL = 0x00000001; // Has Nav signal 288 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER = 0x00000002; // Has localizer 289 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE = 0x00000004; // Has Nav signal 290 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME = 0x00000008; // Station has DME 291 | 292 | 293 | 294 | // bits for the Waypoint Flags field: may be combined 295 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_WAYPOINT_FLAGS; 296 | static const DWORD SIMCONNECT_WAYPOINT_NONE = 0x00; 297 | static const DWORD SIMCONNECT_WAYPOINT_SPEED_REQUESTED = 0x04; // requested speed at waypoint is valid 298 | static const DWORD SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED = 0x08; // request a specific throttle percentage 299 | static const DWORD SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10; // compute vertical to speed to reach waypoint altitude when crossing the waypoint 300 | static const DWORD SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL = 0x20; // AltitudeIsAGL 301 | static const DWORD SIMCONNECT_WAYPOINT_ON_GROUND = 0x00100000; // place this waypoint on the ground 302 | static const DWORD SIMCONNECT_WAYPOINT_REVERSE = 0x00200000; // Back up to this waypoint. Only valid on first waypoint 303 | static const DWORD SIMCONNECT_WAYPOINT_WRAP_TO_FIRST = 0x00400000; // Wrap around back to first waypoint. Only valid on last waypoint. 304 | 305 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_EVENT_FLAG; 306 | static const DWORD SIMCONNECT_EVENT_FLAG_DEFAULT = 0x00000000; 307 | static const DWORD SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001; // set event repeat timer to simulate fast repeat 308 | static const DWORD SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002; // set event repeat timer to simulate slow repeat 309 | static const DWORD SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010; // interpret GroupID parameter as priority value 310 | 311 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_REQUEST_FLAG; 312 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; 313 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested data when value(s) change 314 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested data in tagged format 315 | 316 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_SET_FLAG; 317 | static const DWORD SIMCONNECT_DATA_SET_FLAG_DEFAULT = 0x00000000; 318 | static const DWORD SIMCONNECT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format 319 | 320 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_CREATE_CLIENT_DATA_FLAG; 321 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000; 322 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001; // permit only ClientData creator to write into ClientData 323 | 324 | 325 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_REQUEST_FLAG; 326 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; 327 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested ClientData when value(s) change 328 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested ClientData in tagged format 329 | 330 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_SET_FLAG; 331 | static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT = 0x00000000; 332 | static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format 333 | 334 | 335 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_VIEW_SYSTEM_EVENT_DATA; // dwData contains these flags for the "View" System Event 336 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001; // 2D Panels in cockpit view 337 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002; // Virtual (3D) panels in cockpit view 338 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004; // Orthogonal (Map) view 339 | 340 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_SOUND_SYSTEM_EVENT_DATA; // dwData contains these flags for the "Sound" System Event 341 | static const DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001; // Sound Master 342 | 343 | 344 | #ifdef ENABLE_SIMCONNECT_EXPERIMENTAL 345 | 346 | SIMCONNECT_ENUM_FLAGS SIMCONNECT_PICK_FLAGS 347 | { 348 | SIMCONNECT_PICK_GROUND = 0x01, // pick ground/ pick result item is ground location 349 | SIMCONNECT_PICK_AI = 0x02, // pick AI / pick result item is AI, (dwSimObjectID is valid) 350 | SIMCONNECT_PICK_SCENERY = 0x04, // pick scenery/ pick result item is scenery object (hSceneryObject is valid) 351 | SIMCONNECT_PICK_ALL = SIMCONNECT_PICK_SCENERY | SIMCONNECT_PICK_AI | SIMCONNECT_PICK_GROUND, // pick all / (not valid on pick result item) 352 | SIMCONNECT_PICK_COORDSASPIXELS = 0x08, 353 | }; 354 | 355 | #endif //ENABLE_SIMCONNECT_EXPERIMENTAL 356 | 357 | //---------------------------------------------------------------------------- 358 | // User-defined enums 359 | //---------------------------------------------------------------------------- 360 | 361 | SIMCONNECT_USER_ENUM SIMCONNECT_NOTIFICATION_GROUP_ID; //client-defined notification group ID 362 | SIMCONNECT_USER_ENUM SIMCONNECT_INPUT_GROUP_ID; //client-defined input group ID 363 | SIMCONNECT_USER_ENUM SIMCONNECT_DATA_DEFINITION_ID; //client-defined data definition ID 364 | SIMCONNECT_USER_ENUM SIMCONNECT_DATA_REQUEST_ID; //client-defined request data ID 365 | 366 | SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_EVENT_ID; //client-defined client event ID 367 | SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_ID; //client-defined client data ID 368 | SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_DEFINITION_ID; //client-defined client data definition ID 369 | 370 | 371 | //---------------------------------------------------------------------------- 372 | // Struct definitions 373 | //---------------------------------------------------------------------------- 374 | 375 | #pragma pack(push, 1) 376 | 377 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV 378 | { 379 | DWORD dwSize; // record size 380 | DWORD dwVersion; // interface version 381 | DWORD dwID; // see SIMCONNECT_RECV_ID 382 | }; 383 | 384 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION 385 | { 386 | DWORD dwException; // see SIMCONNECT_EXCEPTION 387 | static const DWORD UNKNOWN_SENDID = 0; 388 | DWORD dwSendID; // see SimConnect_GetLastSentPacketID 389 | static const DWORD UNKNOWN_INDEX = DWORD_MAX; 390 | DWORD dwIndex; // index of parameter that was source of error 391 | }; 392 | 393 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_OPEN : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_OPEN 394 | { 395 | SIMCONNECT_STRING( szApplicationName, 256); 396 | DWORD dwApplicationVersionMajor; 397 | DWORD dwApplicationVersionMinor; 398 | DWORD dwApplicationBuildMajor; 399 | DWORD dwApplicationBuildMinor; 400 | DWORD dwSimConnectVersionMajor; 401 | DWORD dwSimConnectVersionMinor; 402 | DWORD dwSimConnectBuildMajor; 403 | DWORD dwSimConnectBuildMinor; 404 | DWORD dwReserved1; 405 | DWORD dwReserved2; 406 | }; 407 | 408 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_QUIT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_QUIT 409 | { 410 | }; 411 | 412 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT 413 | { 414 | static const DWORD UNKNOWN_GROUP = DWORD_MAX; 415 | DWORD uGroupID; 416 | DWORD uEventID; 417 | DWORD dwData; // uEventID-dependent context 418 | }; 419 | 420 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FILENAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 421 | { 422 | SIMCONNECT_STRING( szFileName, MAX_PATH); // uEventID-dependent context 423 | DWORD dwFlags; 424 | }; 425 | 426 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 427 | { 428 | SIMCONNECT_SIMOBJECT_TYPE eObjType; 429 | }; 430 | 431 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FRAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FRAME 432 | { 433 | float fFrameRate; 434 | float fSimSpeed; 435 | }; 436 | 437 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED 438 | { 439 | // No event specific data, for now 440 | }; 441 | 442 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED 443 | { 444 | // No event specific data, for now 445 | }; 446 | 447 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED 448 | { 449 | // No event specific data, for now 450 | }; 451 | 452 | // SIMCONNECT_DATA_RACE_RESULT 453 | SIMCONNECT_STRUCT SIMCONNECT_DATA_RACE_RESULT 454 | { 455 | DWORD dwNumberOfRacers; // The total number of racers 456 | SIMCONNECT_GUID MissionGUID; // The name of the mission to execute, NULL if no mission 457 | SIMCONNECT_STRING( szPlayerName, MAX_PATH); // The name of the player 458 | SIMCONNECT_STRING( szSessionType, MAX_PATH); // The type of the multiplayer session: "LAN", "GAMESPY") 459 | SIMCONNECT_STRING( szAircraft, MAX_PATH); // The aircraft type 460 | SIMCONNECT_STRING( szPlayerRole, MAX_PATH); // The player role in the mission 461 | double fTotalTime; // Total time in seconds, 0 means DNF 462 | double fPenaltyTime; // Total penalty time in seconds 463 | DWORD dwIsDisqualified; // non 0 - disqualified, 0 - not disqualified 464 | }; 465 | 466 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_END : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_END 467 | { 468 | DWORD dwRacerNumber; // The index of the racer the results are for 469 | SIMCONNECT_DATA_RACE_RESULT RacerData; 470 | }; 471 | 472 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_LAP : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_LAP 473 | { 474 | DWORD dwLapIndex; // The index of the lap the results are for 475 | SIMCONNECT_DATA_RACE_RESULT RacerData; 476 | }; 477 | 478 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA 479 | { 480 | DWORD dwRequestID; 481 | DWORD dwObjectID; 482 | DWORD dwDefineID; 483 | DWORD dwFlags; // SIMCONNECT_DATA_REQUEST_FLAG 484 | DWORD dwentrynumber; // if multiple objects returned, this is number out of . 485 | DWORD dwoutof; // note: starts with 1, not 0. 486 | DWORD dwDefineCount; // data count (number of datums, *not* byte count) 487 | SIMCONNECT_DATAV( dwData, dwDefineID, ); // data begins here, dwDefineCount data items 488 | }; 489 | 490 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE 491 | { 492 | }; 493 | 494 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLIENT_DATA : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_CLIENT_DATA 495 | { 496 | }; 497 | 498 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WEATHER_OBSERVATION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_WEATHER_OBSERVATION 499 | { 500 | DWORD dwRequestID; 501 | SIMCONNECT_STRINGV( szMetar); // Variable length string whose maximum size is MAX_METAR_LENGTH 502 | }; 503 | 504 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH = 64; 505 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_SIZE = SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH*SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH; 506 | 507 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLOUD_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_CLOUD_STATE 508 | { 509 | DWORD dwRequestID; 510 | DWORD dwArraySize; 511 | SIMCONNECT_FIXEDTYPE_DATAV(BYTE, rgbData, dwArraySize, U1 /*member of UnmanagedType enum*/ , System::Byte /*cli type*/); 512 | }; 513 | 514 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ASSIGNED_OBJECT_ID : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID 515 | { 516 | DWORD dwRequestID; 517 | DWORD dwObjectID; 518 | }; 519 | 520 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_RESERVED_KEY : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY 521 | { 522 | SIMCONNECT_STRING( szChoiceReserved, 30); 523 | SIMCONNECT_STRING( szReservedKey, 50); 524 | }; 525 | 526 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SYSTEM_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SYSTEM_STATE 527 | { 528 | DWORD dwRequestID; 529 | DWORD dwInteger; 530 | float fFloat; 531 | SIMCONNECT_STRING( szString, MAX_PATH); 532 | }; 533 | 534 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CUSTOM_ACTION : public SIMCONNECT_RECV_EVENT 535 | { 536 | SIMCONNECT_GUID guidInstanceId; // Instance id of the action that executed 537 | DWORD dwWaitForCompletion; // Wait for completion flag on the action 538 | SIMCONNECT_STRINGV( szPayLoad); // Variable length string payload associated with the mission action. 539 | }; 540 | 541 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_WEATHER_MODE : public SIMCONNECT_RECV_EVENT 542 | { 543 | // No event specific data - the new weather mode is in the base structure dwData member. 544 | }; 545 | 546 | // SIMCONNECT_RECV_FACILITIES_LIST 547 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITIES_LIST : public SIMCONNECT_RECV 548 | { 549 | DWORD dwRequestID; 550 | DWORD dwArraySize; 551 | DWORD dwEntryNumber; // when the array of items is too big for one send, which send this is (0..dwOutOf-1) 552 | DWORD dwOutOf; // total number of transmissions the list is chopped into 553 | }; 554 | 555 | // SIMCONNECT_DATA_FACILITY_AIRPORT 556 | SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_AIRPORT 557 | { 558 | SIMCONNECT_STRING(Icao, 9); // ICAO of the object 559 | double Latitude; // degrees 560 | double Longitude; // degrees 561 | double Altitude; // meters 562 | }; 563 | 564 | // SIMCONNECT_RECV_AIRPORT_LIST 565 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_AIRPORT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 566 | { 567 | SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_AIRPORT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_AIRPORT /*cli type*/); 568 | }; 569 | 570 | 571 | // SIMCONNECT_DATA_FACILITY_WAYPOINT 572 | SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_WAYPOINT : public SIMCONNECT_DATA_FACILITY_AIRPORT 573 | { 574 | float fMagVar; // Magvar in degrees 575 | }; 576 | 577 | // SIMCONNECT_RECV_WAYPOINT_LIST 578 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WAYPOINT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 579 | { 580 | SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_WAYPOINT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_WAYPOINT /*cli type*/); 581 | }; 582 | 583 | // SIMCONNECT_DATA_FACILITY_NDB 584 | SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_NDB : public SIMCONNECT_DATA_FACILITY_WAYPOINT 585 | { 586 | DWORD fFrequency; // frequency in Hz 587 | }; 588 | 589 | // SIMCONNECT_RECV_NDB_LIST 590 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_NDB_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 591 | { 592 | SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_NDB, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_NDB /*cli type*/); 593 | }; 594 | 595 | // SIMCONNECT_DATA_FACILITY_VOR 596 | SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_VOR : public SIMCONNECT_DATA_FACILITY_NDB 597 | { 598 | DWORD Flags; // SIMCONNECT_VOR_FLAGS 599 | float fLocalizer; // Localizer in degrees 600 | double GlideLat; // Glide Slope Location (deg, deg, meters) 601 | double GlideLon; 602 | double GlideAlt; 603 | float fGlideSlopeAngle; // Glide Slope in degrees 604 | }; 605 | 606 | // SIMCONNECT_RECV_VOR_LIST 607 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_VOR_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 608 | { 609 | SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_VOR, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_VOR /*cli type*/); 610 | }; 611 | 612 | #ifdef ENABLE_SIMCONNECT_EXPERIMENTAL 613 | 614 | SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_PICK : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY 615 | { 616 | HANDLE hContext; 617 | DWORD dwFlags; // 618 | double Latitude; // degrees 619 | double Longitude; // degrees 620 | double Altitude; // feet 621 | int xPos; //reserved 622 | int yPos; //reserved; 623 | DWORD dwSimObjectID; 624 | HANDLE hSceneryObject; 625 | DWORD dwentrynumber; // if multiple objects returned, this is number out of . 626 | DWORD dwoutof; // note: starts with 1, not 0. 627 | }; 628 | 629 | #endif //ENABLE_SIMCONNECT_EXPERIMENTAL 630 | 631 | 632 | // SIMCONNECT_DATATYPE_INITPOSITION 633 | SIMCONNECT_STRUCT SIMCONNECT_DATA_INITPOSITION 634 | { 635 | double Latitude; // degrees 636 | double Longitude; // degrees 637 | double Altitude; // feet 638 | double Pitch; // degrees 639 | double Bank; // degrees 640 | double Heading; // degrees 641 | DWORD OnGround; // 1=force to be on the ground 642 | DWORD Airspeed; // knots 643 | }; 644 | 645 | 646 | // SIMCONNECT_DATATYPE_MARKERSTATE 647 | SIMCONNECT_STRUCT SIMCONNECT_DATA_MARKERSTATE 648 | { 649 | SIMCONNECT_STRING( szMarkerName, 64); 650 | DWORD dwMarkerState; 651 | }; 652 | 653 | // SIMCONNECT_DATATYPE_WAYPOINT 654 | SIMCONNECT_STRUCT SIMCONNECT_DATA_WAYPOINT 655 | { 656 | double Latitude; // degrees 657 | double Longitude; // degrees 658 | double Altitude; // feet 659 | unsigned long Flags; 660 | double ktsSpeed; // knots 661 | double percentThrottle; 662 | }; 663 | 664 | // SIMCONNECT_DATA_LATLONALT 665 | SIMCONNECT_STRUCT SIMCONNECT_DATA_LATLONALT 666 | { 667 | double Latitude; 668 | double Longitude; 669 | double Altitude; 670 | }; 671 | 672 | // SIMCONNECT_DATA_XYZ 673 | SIMCONNECT_STRUCT SIMCONNECT_DATA_XYZ 674 | { 675 | double x; 676 | double y; 677 | double z; 678 | }; 679 | 680 | #pragma pack(pop) 681 | 682 | //---------------------------------------------------------------------------- 683 | // End of Struct definitions 684 | //---------------------------------------------------------------------------- 685 | 686 | typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); 687 | 688 | #if !defined(SIMCONNECTAPI) 689 | #ifdef _MSFS_WASM 690 | #ifdef __INTELLISENSE__ 691 | #define MODULE_EXPORT 692 | #define SIMCONNECTAPI extern "C" HRESULT 693 | #else 694 | #define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) ) 695 | #define SIMCONNECTAPI extern "C" __attribute__((import_module(SIMCONNECT_WASM_MODULE))) HRESULT 696 | #endif 697 | #else 698 | #define MODULE_EXPORT 699 | #define SIMCONNECTAPI extern "C" HRESULT __stdcall 700 | #endif 701 | #endif 702 | 703 | SIMCONNECTAPI SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName = ""); 704 | SIMCONNECTAPI SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags); 705 | SIMCONNECTAPI SimConnect_SetSystemEventState(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_STATE dwState); 706 | SIMCONNECTAPI SimConnect_AddClientEventToNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable = FALSE); 707 | SIMCONNECTAPI SimConnect_RemoveClientEvent(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID); 708 | SIMCONNECTAPI SimConnect_SetNotificationGroupPriority(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); 709 | SIMCONNECTAPI SimConnect_ClearNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID); 710 | SIMCONNECTAPI SimConnect_RequestNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD dwReserved = 0, DWORD Flags = 0); 711 | SIMCONNECTAPI SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * DatumName, const char * UnitsName, SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); 712 | SIMCONNECTAPI SimConnect_ClearDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); 713 | SIMCONNECTAPI SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); 714 | SIMCONNECTAPI SimConnect_RequestDataOnSimObjectType(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, DWORD dwRadiusMeters, SIMCONNECT_SIMOBJECT_TYPE type); 715 | SIMCONNECTAPI SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); 716 | SIMCONNECTAPI SimConnect_MapInputEventToClientEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); 717 | SIMCONNECTAPI SimConnect_SetInputGroupPriority(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD uPriority); 718 | SIMCONNECTAPI SimConnect_RemoveInputEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition); 719 | SIMCONNECTAPI SimConnect_ClearInputGroup(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID); 720 | SIMCONNECTAPI SimConnect_SetInputGroupState(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD dwState); 721 | SIMCONNECTAPI SimConnect_RequestReservedKey(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * szKeyChoice1 = "", const char * szKeyChoice2 = "", const char * szKeyChoice3 = ""); 722 | SIMCONNECTAPI SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); 723 | SIMCONNECTAPI SimConnect_UnsubscribeFromSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); 724 | SIMCONNECTAPI SimConnect_WeatherRequestInterpolatedObservation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt); 725 | SIMCONNECTAPI SimConnect_WeatherRequestObservationAtStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 726 | SIMCONNECTAPI SimConnect_WeatherRequestObservationAtNearestStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon); 727 | SIMCONNECTAPI SimConnect_WeatherCreateStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO, const char * szName, float lat, float lon, float alt); 728 | SIMCONNECTAPI SimConnect_WeatherRemoveStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 729 | SIMCONNECTAPI SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char * szMETAR); 730 | SIMCONNECTAPI SimConnect_WeatherSetModeServer(HANDLE hSimConnect, DWORD dwPort, DWORD dwSeconds); 731 | SIMCONNECTAPI SimConnect_WeatherSetModeTheme(HANDLE hSimConnect, const char * szThemeName); 732 | SIMCONNECTAPI SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect); 733 | SIMCONNECTAPI SimConnect_WeatherSetModeCustom(HANDLE hSimConnect); 734 | SIMCONNECTAPI SimConnect_WeatherSetDynamicUpdateRate(HANDLE hSimConnect, DWORD dwRate); 735 | SIMCONNECTAPI SimConnect_WeatherRequestCloudState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float minLat, float minLon, float minAlt, float maxLat, float maxLon, float maxAlt, DWORD dwFlags = 0); 736 | SIMCONNECTAPI SimConnect_WeatherCreateThermal(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt, float radius, float height, float coreRate = 3.0f, float coreTurbulence = 0.05f, float sinkRate = 3.0f, float sinkTurbulence = 0.2f, float coreSize = 0.4f, float coreTransitionSize = 0.1f, float sinkLayerSize = 0.4f, float sinkTransitionSize = 0.1f); 737 | SIMCONNECTAPI SimConnect_WeatherRemoveThermal(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID); 738 | SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); 739 | SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); 740 | SIMCONNECTAPI SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 741 | SIMCONNECTAPI SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char * szContainerTitle, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 742 | SIMCONNECTAPI SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 743 | SIMCONNECTAPI SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 744 | SIMCONNECTAPI SimConnect_AISetAircraftFlightPlan(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, const char * szFlightPlanPath, SIMCONNECT_DATA_REQUEST_ID RequestID); 745 | SIMCONNECTAPI SimConnect_ExecuteMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 746 | SIMCONNECTAPI SimConnect_CompleteCustomMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 747 | SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect); 748 | SIMCONNECTAPI SimConnect_RetrieveString(SIMCONNECT_RECV * pData, DWORD cbData, void * pStringV, char ** pszString, DWORD * pcbString); 749 | SIMCONNECTAPI SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD * pdwError); 750 | SIMCONNECTAPI SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); 751 | SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); 752 | SIMCONNECTAPI SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData); 753 | SIMCONNECTAPI SimConnect_RequestResponseTimes(HANDLE hSimConnect, DWORD nCount, float * fElapsedSeconds); 754 | SIMCONNECTAPI SimConnect_InsertString(char * pDest, DWORD cbDest, void ** ppEnd, DWORD * pcbStringV, const char * pSource); 755 | SIMCONNECTAPI SimConnect_CameraSetRelative6DOF(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg); 756 | SIMCONNECTAPI SimConnect_MenuAddItem(HANDLE hSimConnect, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, DWORD dwData); 757 | SIMCONNECTAPI SimConnect_MenuDeleteItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID); 758 | SIMCONNECTAPI SimConnect_MenuAddSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID, DWORD dwData); 759 | SIMCONNECTAPI SimConnect_MenuDeleteSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID); 760 | SIMCONNECTAPI SimConnect_RequestSystemState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szState); 761 | SIMCONNECTAPI SimConnect_SetSystemState(HANDLE hSimConnect, const char * szState, DWORD dwInteger, float fFloat, const char * szString); 762 | SIMCONNECTAPI SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char * szClientDataName, SIMCONNECT_CLIENT_DATA_ID ClientDataID); 763 | SIMCONNECTAPI SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags); 764 | SIMCONNECTAPI SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwOffset, DWORD dwSizeOrType, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); 765 | SIMCONNECTAPI SimConnect_ClearClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID); 766 | SIMCONNECTAPI SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_PERIOD Period = SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); 767 | SIMCONNECTAPI SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_SET_FLAG Flags, DWORD dwReserved, DWORD cbUnitSize, void * pDataSet); 768 | SIMCONNECTAPI SimConnect_FlightLoad(HANDLE hSimConnect, const char * szFileName); 769 | SIMCONNECTAPI SimConnect_FlightSave(HANDLE hSimConnect, const char * szFileName, const char * szTitle, const char * szDescription, DWORD Flags); 770 | SIMCONNECTAPI SimConnect_FlightPlanLoad(HANDLE hSimConnect, const char * szFileName); 771 | SIMCONNECTAPI SimConnect_Text(HANDLE hSimConnect, SIMCONNECT_TEXT_TYPE type, float fTimeSeconds, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD cbUnitSize, void * pDataSet); 772 | SIMCONNECTAPI SimConnect_SubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); 773 | SIMCONNECTAPI SimConnect_UnsubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type); 774 | SIMCONNECTAPI SimConnect_RequestFacilitiesList(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); 775 | 776 | #endif // _SIMCONNECT_H_ 777 | -------------------------------------------------------------------------------- /scripts/SimConnect_cpp.h: -------------------------------------------------------------------------------- 1 | # 0 "SimConnect.h" 2 | # 0 "" 3 | # 0 "" 4 | # 1 "SimConnect.h" 5 | //----------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) Microsoft Corporation. All Rights Reserved. 8 | // 9 | //----------------------------------------------------------------------------- 10 | 11 | 12 | 13 | 14 | 15 | # 22 "SimConnect.h" 16 | # 1 "./float.h" 1 17 | # 23 "SimConnect.h" 2 18 | 19 | typedef DWORD SIMCONNECT_OBJECT_ID; 20 | 21 | //---------------------------------------------------------------------------- 22 | // Constants 23 | //---------------------------------------------------------------------------- 24 | 25 | static const DWORD SIMCONNECT_UNUSED = 0xFFFFFFFF; // special value to indicate unused event, ID 26 | static const DWORD SIMCONNECT_OBJECT_ID_USER = 0; // proxy value for User vehicle ObjectID 27 | 28 | static const float SIMCONNECT_CAMERA_IGNORE_FIELD = FLT_MAX; //Used to tell the Camera API to NOT modify the value in this part of the argument. 29 | 30 | static const DWORD SIMCONNECT_CLIENTDATA_MAX_SIZE = 8192; // maximum value for SimConnect_CreateClientData dwSize parameter 31 | 32 | 33 | // Notification Group priority values 34 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority 35 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000; // highest priority that allows events to be masked 36 | static const DWORD SIMCONNECT_GROUP_PRIORITY_STANDARD = 1900000000; // standard priority 37 | static const DWORD SIMCONNECT_GROUP_PRIORITY_DEFAULT = 2000000000; // default priority 38 | static const DWORD SIMCONNECT_GROUP_PRIORITY_LOWEST = 4000000000; // priorities lower than this will be ignored 39 | 40 | //Weather observations Metar strings 41 | static const DWORD MAX_METAR_LENGTH = 2000; 42 | 43 | // Maximum thermal size is 100 km. 44 | static const float MAX_THERMAL_SIZE = 100000; 45 | static const float MAX_THERMAL_RATE = 1000; 46 | 47 | // SIMCONNECT_DATA_INITPOSITION.Airspeed 48 | static const DWORD INITPOSITION_AIRSPEED_CRUISE = -1; // aircraft's cruise airspeed 49 | static const DWORD INITPOSITION_AIRSPEED_KEEP = -2; // keep current airspeed 50 | 51 | // AddToClientDataDefinition dwSizeOrType parameter type values 52 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT8 = -1; // 8-bit integer number 53 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT16 = -2; // 16-bit integer number 54 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT32 = -3; // 32-bit integer number 55 | static const DWORD SIMCONNECT_CLIENTDATATYPE_INT64 = -4; // 64-bit integer number 56 | static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT32 = -5; // 32-bit floating-point number (float) 57 | static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT64 = -6; // 64-bit floating-point number (double) 58 | 59 | // AddToClientDataDefinition dwOffset parameter special values 60 | static const DWORD SIMCONNECT_CLIENTDATAOFFSET_AUTO = -1; // automatically compute offset of the ClientData variable 61 | 62 | // Open ConfigIndex parameter special value 63 | static const DWORD SIMCONNECT_OPEN_CONFIGINDEX_LOCAL = -1; // ignore SimConnect.cfg settings, and force local connection 64 | 65 | //---------------------------------------------------------------------------- 66 | // Enum definitions 67 | //---------------------------------------------------------------------------- 68 | 69 | //these came from substituteMacros 70 | # 88 "SimConnect.h" 71 | // Receive data types 72 | enum SIMCONNECT_RECV_ID { 73 | SIMCONNECT_RECV_ID_NULL, 74 | SIMCONNECT_RECV_ID_EXCEPTION, 75 | SIMCONNECT_RECV_ID_OPEN, 76 | SIMCONNECT_RECV_ID_QUIT, 77 | SIMCONNECT_RECV_ID_EVENT, 78 | SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE, 79 | SIMCONNECT_RECV_ID_EVENT_FILENAME, 80 | SIMCONNECT_RECV_ID_EVENT_FRAME, 81 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA, 82 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE, 83 | SIMCONNECT_RECV_ID_WEATHER_OBSERVATION, 84 | SIMCONNECT_RECV_ID_CLOUD_STATE, 85 | SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID, 86 | SIMCONNECT_RECV_ID_RESERVED_KEY, 87 | SIMCONNECT_RECV_ID_CUSTOM_ACTION, 88 | SIMCONNECT_RECV_ID_SYSTEM_STATE, 89 | SIMCONNECT_RECV_ID_CLIENT_DATA, 90 | SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE, 91 | SIMCONNECT_RECV_ID_AIRPORT_LIST, 92 | SIMCONNECT_RECV_ID_VOR_LIST, 93 | SIMCONNECT_RECV_ID_NDB_LIST, 94 | SIMCONNECT_RECV_ID_WAYPOINT_LIST, 95 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED, 96 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED, 97 | SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED, 98 | SIMCONNECT_RECV_ID_EVENT_RACE_END, 99 | SIMCONNECT_RECV_ID_EVENT_RACE_LAP, 100 | 101 | 102 | 103 | }; 104 | 105 | 106 | 107 | // Data data types 108 | enum SIMCONNECT_DATATYPE { 109 | SIMCONNECT_DATATYPE_INVALID, // invalid data type 110 | SIMCONNECT_DATATYPE_INT32, // 32-bit integer number 111 | SIMCONNECT_DATATYPE_INT64, // 64-bit integer number 112 | SIMCONNECT_DATATYPE_FLOAT32, // 32-bit floating-point number (float) 113 | SIMCONNECT_DATATYPE_FLOAT64, // 64-bit floating-point number (double) 114 | SIMCONNECT_DATATYPE_STRING8, // 8-byte string 115 | SIMCONNECT_DATATYPE_STRING32, // 32-byte string 116 | SIMCONNECT_DATATYPE_STRING64, // 64-byte string 117 | SIMCONNECT_DATATYPE_STRING128, // 128-byte string 118 | SIMCONNECT_DATATYPE_STRING256, // 256-byte string 119 | SIMCONNECT_DATATYPE_STRING260, // 260-byte string 120 | SIMCONNECT_DATATYPE_STRINGV, // variable-length string 121 | 122 | SIMCONNECT_DATATYPE_INITPOSITION, // see SIMCONNECT_DATA_INITPOSITION 123 | SIMCONNECT_DATATYPE_MARKERSTATE, // see SIMCONNECT_DATA_MARKERSTATE 124 | SIMCONNECT_DATATYPE_WAYPOINT, // see SIMCONNECT_DATA_WAYPOINT 125 | SIMCONNECT_DATATYPE_LATLONALT, // see SIMCONNECT_DATA_LATLONALT 126 | SIMCONNECT_DATATYPE_XYZ, // see SIMCONNECT_DATA_XYZ 127 | 128 | SIMCONNECT_DATATYPE_MAX // enum limit 129 | }; 130 | 131 | // Exception error types 132 | enum SIMCONNECT_EXCEPTION { 133 | SIMCONNECT_EXCEPTION_NONE, 134 | 135 | SIMCONNECT_EXCEPTION_ERROR, 136 | SIMCONNECT_EXCEPTION_SIZE_MISMATCH, 137 | SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, 138 | SIMCONNECT_EXCEPTION_UNOPENED, 139 | SIMCONNECT_EXCEPTION_VERSION_MISMATCH, 140 | SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, 141 | SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, 142 | SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, 143 | SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, 144 | SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, 145 | SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, 146 | SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, 147 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, 148 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, 149 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, 150 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, 151 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, 152 | SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, 153 | SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, 154 | SIMCONNECT_EXCEPTION_DATA_ERROR, 155 | SIMCONNECT_EXCEPTION_INVALID_ARRAY, 156 | SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, 157 | SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED, 158 | SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, 159 | SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, 160 | SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, 161 | SIMCONNECT_EXCEPTION_INVALID_ENUM, 162 | SIMCONNECT_EXCEPTION_DEFINITION_ERROR, 163 | SIMCONNECT_EXCEPTION_DUPLICATE_ID, 164 | SIMCONNECT_EXCEPTION_DATUM_ID, 165 | SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, 166 | SIMCONNECT_EXCEPTION_ALREADY_CREATED, 167 | SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE, 168 | SIMCONNECT_EXCEPTION_OBJECT_CONTAINER, 169 | SIMCONNECT_EXCEPTION_OBJECT_AI, 170 | SIMCONNECT_EXCEPTION_OBJECT_ATC, 171 | SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE, 172 | }; 173 | 174 | // Object types 175 | enum SIMCONNECT_SIMOBJECT_TYPE { 176 | SIMCONNECT_SIMOBJECT_TYPE_USER, 177 | SIMCONNECT_SIMOBJECT_TYPE_ALL, 178 | SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, 179 | SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER, 180 | SIMCONNECT_SIMOBJECT_TYPE_BOAT, 181 | SIMCONNECT_SIMOBJECT_TYPE_GROUND, 182 | }; 183 | 184 | // EventState values 185 | enum SIMCONNECT_STATE { 186 | SIMCONNECT_STATE_OFF, 187 | SIMCONNECT_STATE_ON, 188 | }; 189 | 190 | // Object Data Request Period values 191 | enum SIMCONNECT_PERIOD { 192 | SIMCONNECT_PERIOD_NEVER, 193 | SIMCONNECT_PERIOD_ONCE, 194 | SIMCONNECT_PERIOD_VISUAL_FRAME, 195 | SIMCONNECT_PERIOD_SIM_FRAME, 196 | SIMCONNECT_PERIOD_SECOND, 197 | }; 198 | 199 | 200 | enum SIMCONNECT_MISSION_END { 201 | SIMCONNECT_MISSION_FAILED, 202 | SIMCONNECT_MISSION_CRASHED, 203 | SIMCONNECT_MISSION_SUCCEEDED 204 | }; 205 | 206 | // ClientData Request Period values 207 | enum SIMCONNECT_CLIENT_DATA_PERIOD { 208 | SIMCONNECT_CLIENT_DATA_PERIOD_NEVER, 209 | SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, 210 | SIMCONNECT_CLIENT_DATA_PERIOD_VISUAL_FRAME, 211 | SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, 212 | SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, 213 | }; 214 | 215 | enum SIMCONNECT_TEXT_TYPE { 216 | SIMCONNECT_TEXT_TYPE_SCROLL_BLACK, 217 | SIMCONNECT_TEXT_TYPE_SCROLL_WHITE, 218 | SIMCONNECT_TEXT_TYPE_SCROLL_RED, 219 | SIMCONNECT_TEXT_TYPE_SCROLL_GREEN, 220 | SIMCONNECT_TEXT_TYPE_SCROLL_BLUE, 221 | SIMCONNECT_TEXT_TYPE_SCROLL_YELLOW, 222 | SIMCONNECT_TEXT_TYPE_SCROLL_MAGENTA, 223 | SIMCONNECT_TEXT_TYPE_SCROLL_CYAN, 224 | SIMCONNECT_TEXT_TYPE_PRINT_BLACK=0x0100, 225 | SIMCONNECT_TEXT_TYPE_PRINT_WHITE, 226 | SIMCONNECT_TEXT_TYPE_PRINT_RED, 227 | SIMCONNECT_TEXT_TYPE_PRINT_GREEN, 228 | SIMCONNECT_TEXT_TYPE_PRINT_BLUE, 229 | SIMCONNECT_TEXT_TYPE_PRINT_YELLOW, 230 | SIMCONNECT_TEXT_TYPE_PRINT_MAGENTA, 231 | SIMCONNECT_TEXT_TYPE_PRINT_CYAN, 232 | SIMCONNECT_TEXT_TYPE_MENU=0x0200, 233 | }; 234 | 235 | enum SIMCONNECT_TEXT_RESULT { 236 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_1, 237 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_2, 238 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_3, 239 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_4, 240 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_5, 241 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_6, 242 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_7, 243 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_8, 244 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_9, 245 | SIMCONNECT_TEXT_RESULT_MENU_SELECT_10, 246 | SIMCONNECT_TEXT_RESULT_DISPLAYED = 0x00010000, 247 | SIMCONNECT_TEXT_RESULT_QUEUED, 248 | SIMCONNECT_TEXT_RESULT_REMOVED, 249 | SIMCONNECT_TEXT_RESULT_REPLACED, 250 | SIMCONNECT_TEXT_RESULT_TIMEOUT, 251 | }; 252 | 253 | enum SIMCONNECT_WEATHER_MODE { 254 | SIMCONNECT_WEATHER_MODE_THEME, 255 | SIMCONNECT_WEATHER_MODE_RWW, 256 | SIMCONNECT_WEATHER_MODE_CUSTOM, 257 | SIMCONNECT_WEATHER_MODE_GLOBAL, 258 | }; 259 | 260 | enum SIMCONNECT_FACILITY_LIST_TYPE { 261 | SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, 262 | SIMCONNECT_FACILITY_LIST_TYPE_WAYPOINT, 263 | SIMCONNECT_FACILITY_LIST_TYPE_NDB, 264 | SIMCONNECT_FACILITY_LIST_TYPE_VOR, 265 | SIMCONNECT_FACILITY_LIST_TYPE_COUNT // invalid 266 | }; 267 | 268 | 269 | typedef DWORD SIMCONNECT_VOR_FLAGS; // flags for SIMCONNECT_RECV_ID_VOR_LIST 270 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL = 0x00000001; // Has Nav signal 271 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER = 0x00000002; // Has localizer 272 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE = 0x00000004; // Has Nav signal 273 | static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME = 0x00000008; // Station has DME 274 | 275 | 276 | 277 | // bits for the Waypoint Flags field: may be combined 278 | typedef DWORD SIMCONNECT_WAYPOINT_FLAGS; 279 | static const DWORD SIMCONNECT_WAYPOINT_NONE = 0x00; 280 | static const DWORD SIMCONNECT_WAYPOINT_SPEED_REQUESTED = 0x04; // requested speed at waypoint is valid 281 | static const DWORD SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED = 0x08; // request a specific throttle percentage 282 | static const DWORD SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10; // compute vertical to speed to reach waypoint altitude when crossing the waypoint 283 | static const DWORD SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL = 0x20; // AltitudeIsAGL 284 | static const DWORD SIMCONNECT_WAYPOINT_ON_GROUND = 0x00100000; // place this waypoint on the ground 285 | static const DWORD SIMCONNECT_WAYPOINT_REVERSE = 0x00200000; // Back up to this waypoint. Only valid on first waypoint 286 | static const DWORD SIMCONNECT_WAYPOINT_WRAP_TO_FIRST = 0x00400000; // Wrap around back to first waypoint. Only valid on last waypoint. 287 | 288 | typedef DWORD SIMCONNECT_EVENT_FLAG; 289 | static const DWORD SIMCONNECT_EVENT_FLAG_DEFAULT = 0x00000000; 290 | static const DWORD SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001; // set event repeat timer to simulate fast repeat 291 | static const DWORD SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002; // set event repeat timer to simulate slow repeat 292 | static const DWORD SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010; // interpret GroupID parameter as priority value 293 | 294 | typedef DWORD SIMCONNECT_DATA_REQUEST_FLAG; 295 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; 296 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested data when value(s) change 297 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested data in tagged format 298 | 299 | typedef DWORD SIMCONNECT_DATA_SET_FLAG; 300 | static const DWORD SIMCONNECT_DATA_SET_FLAG_DEFAULT = 0x00000000; 301 | static const DWORD SIMCONNECT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format 302 | 303 | typedef DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG; 304 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000; 305 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001; // permit only ClientData creator to write into ClientData 306 | 307 | 308 | typedef DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG; 309 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; 310 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested ClientData when value(s) change 311 | static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested ClientData in tagged format 312 | 313 | typedef DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG; 314 | static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT = 0x00000000; 315 | static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format 316 | 317 | 318 | typedef DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA; // dwData contains these flags for the "View" System Event 319 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001; // 2D Panels in cockpit view 320 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002; // Virtual (3D) panels in cockpit view 321 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004; // Orthogonal (Map) view 322 | 323 | typedef DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA; // dwData contains these flags for the "Sound" System Event 324 | static const DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001; // Sound Master 325 | # 357 "SimConnect.h" 326 | //---------------------------------------------------------------------------- 327 | // User-defined enums 328 | //---------------------------------------------------------------------------- 329 | 330 | typedef DWORD SIMCONNECT_NOTIFICATION_GROUP_ID; //client-defined notification group ID 331 | typedef DWORD SIMCONNECT_INPUT_GROUP_ID; //client-defined input group ID 332 | typedef DWORD SIMCONNECT_DATA_DEFINITION_ID; //client-defined data definition ID 333 | typedef DWORD SIMCONNECT_DATA_REQUEST_ID; //client-defined request data ID 334 | 335 | typedef DWORD SIMCONNECT_CLIENT_EVENT_ID; //client-defined client event ID 336 | typedef DWORD SIMCONNECT_CLIENT_DATA_ID; //client-defined client data ID 337 | typedef DWORD SIMCONNECT_CLIENT_DATA_DEFINITION_ID; //client-defined client data definition ID 338 | 339 | 340 | //---------------------------------------------------------------------------- 341 | // Struct definitions 342 | //---------------------------------------------------------------------------- 343 | 344 | #pragma pack(push, 1) 345 | 346 | struct SIMCONNECT_RECV 347 | { 348 | DWORD dwSize; // record size 349 | DWORD dwVersion; // interface version 350 | DWORD dwID; // see SIMCONNECT_RECV_ID 351 | }; 352 | 353 | struct SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION 354 | { 355 | DWORD dwException; // see SIMCONNECT_EXCEPTION 356 | static const DWORD UNKNOWN_SENDID = 0; 357 | DWORD dwSendID; // see SimConnect_GetLastSentPacketID 358 | static const DWORD UNKNOWN_INDEX = 0xFFFFFFFF; 359 | DWORD dwIndex; // index of parameter that was source of error 360 | }; 361 | 362 | struct SIMCONNECT_RECV_OPEN : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_OPEN 363 | { 364 | char szApplicationName[256]; 365 | DWORD dwApplicationVersionMajor; 366 | DWORD dwApplicationVersionMinor; 367 | DWORD dwApplicationBuildMajor; 368 | DWORD dwApplicationBuildMinor; 369 | DWORD dwSimConnectVersionMajor; 370 | DWORD dwSimConnectVersionMinor; 371 | DWORD dwSimConnectBuildMajor; 372 | DWORD dwSimConnectBuildMinor; 373 | DWORD dwReserved1; 374 | DWORD dwReserved2; 375 | }; 376 | 377 | struct SIMCONNECT_RECV_QUIT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_QUIT 378 | { 379 | }; 380 | 381 | struct SIMCONNECT_RECV_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT 382 | { 383 | static const DWORD UNKNOWN_GROUP = 0xFFFFFFFF; 384 | DWORD uGroupID; 385 | DWORD uEventID; 386 | DWORD dwData; // uEventID-dependent context 387 | }; 388 | 389 | struct SIMCONNECT_RECV_EVENT_FILENAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 390 | { 391 | char szFileName[MAX_PATH]; // uEventID-dependent context 392 | DWORD dwFlags; 393 | }; 394 | 395 | struct SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 396 | { 397 | SIMCONNECT_SIMOBJECT_TYPE eObjType; 398 | }; 399 | 400 | struct SIMCONNECT_RECV_EVENT_FRAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FRAME 401 | { 402 | float fFrameRate; 403 | float fSimSpeed; 404 | }; 405 | 406 | struct SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED 407 | { 408 | // No event specific data, for now 409 | }; 410 | 411 | struct SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED 412 | { 413 | // No event specific data, for now 414 | }; 415 | 416 | struct SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED 417 | { 418 | // No event specific data, for now 419 | }; 420 | 421 | // SIMCONNECT_DATA_RACE_RESULT 422 | struct SIMCONNECT_DATA_RACE_RESULT 423 | { 424 | DWORD dwNumberOfRacers; // The total number of racers 425 | GUID MissionGUID; // The name of the mission to execute, NULL if no mission 426 | char szPlayerName[MAX_PATH]; // The name of the player 427 | char szSessionType[MAX_PATH]; // The type of the multiplayer session: "LAN", "GAMESPY") 428 | char szAircraft[MAX_PATH]; // The aircraft type 429 | char szPlayerRole[MAX_PATH]; // The player role in the mission 430 | double fTotalTime; // Total time in seconds, 0 means DNF 431 | double fPenaltyTime; // Total penalty time in seconds 432 | DWORD dwIsDisqualified; // non 0 - disqualified, 0 - not disqualified 433 | }; 434 | 435 | struct SIMCONNECT_RECV_EVENT_RACE_END : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_END 436 | { 437 | DWORD dwRacerNumber; // The index of the racer the results are for 438 | SIMCONNECT_DATA_RACE_RESULT RacerData; 439 | }; 440 | 441 | struct SIMCONNECT_RECV_EVENT_RACE_LAP : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_LAP 442 | { 443 | DWORD dwLapIndex; // The index of the lap the results are for 444 | SIMCONNECT_DATA_RACE_RESULT RacerData; 445 | }; 446 | 447 | struct SIMCONNECT_RECV_SIMOBJECT_DATA : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA 448 | { 449 | DWORD dwRequestID; 450 | DWORD dwObjectID; 451 | DWORD dwDefineID; 452 | DWORD dwFlags; // SIMCONNECT_DATA_REQUEST_FLAG 453 | DWORD dwentrynumber; // if multiple objects returned, this is number out of . 454 | DWORD dwoutof; // note: starts with 1, not 0. 455 | DWORD dwDefineCount; // data count (number of datums, *not* byte count) 456 | DWORD dwData; // data begins here, dwDefineCount data items 457 | }; 458 | 459 | struct SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE 460 | { 461 | }; 462 | 463 | struct SIMCONNECT_RECV_CLIENT_DATA : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_CLIENT_DATA 464 | { 465 | }; 466 | 467 | struct SIMCONNECT_RECV_WEATHER_OBSERVATION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_WEATHER_OBSERVATION 468 | { 469 | DWORD dwRequestID; 470 | char szMetar[1]; // Variable length string whose maximum size is MAX_METAR_LENGTH 471 | }; 472 | 473 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH = 64; 474 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_SIZE = SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH*SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH; 475 | 476 | struct SIMCONNECT_RECV_CLOUD_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_CLOUD_STATE 477 | { 478 | DWORD dwRequestID; 479 | DWORD dwArraySize; 480 | BYTE rgbData[1]; 481 | }; 482 | 483 | struct SIMCONNECT_RECV_ASSIGNED_OBJECT_ID : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID 484 | { 485 | DWORD dwRequestID; 486 | DWORD dwObjectID; 487 | }; 488 | 489 | struct SIMCONNECT_RECV_RESERVED_KEY : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY 490 | { 491 | char szChoiceReserved[30]; 492 | char szReservedKey[50]; 493 | }; 494 | 495 | struct SIMCONNECT_RECV_SYSTEM_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SYSTEM_STATE 496 | { 497 | DWORD dwRequestID; 498 | DWORD dwInteger; 499 | float fFloat; 500 | char szString[MAX_PATH]; 501 | }; 502 | 503 | struct SIMCONNECT_RECV_CUSTOM_ACTION : public SIMCONNECT_RECV_EVENT 504 | { 505 | GUID guidInstanceId; // Instance id of the action that executed 506 | DWORD dwWaitForCompletion; // Wait for completion flag on the action 507 | char szPayLoad[1]; // Variable length string payload associated with the mission action. 508 | }; 509 | 510 | struct SIMCONNECT_RECV_EVENT_WEATHER_MODE : public SIMCONNECT_RECV_EVENT 511 | { 512 | // No event specific data - the new weather mode is in the base structure dwData member. 513 | }; 514 | 515 | // SIMCONNECT_RECV_FACILITIES_LIST 516 | struct SIMCONNECT_RECV_FACILITIES_LIST : public SIMCONNECT_RECV 517 | { 518 | DWORD dwRequestID; 519 | DWORD dwArraySize; 520 | DWORD dwEntryNumber; // when the array of items is too big for one send, which send this is (0..dwOutOf-1) 521 | DWORD dwOutOf; // total number of transmissions the list is chopped into 522 | }; 523 | 524 | // SIMCONNECT_DATA_FACILITY_AIRPORT 525 | struct SIMCONNECT_DATA_FACILITY_AIRPORT 526 | { 527 | char Icao[9]; // ICAO of the object 528 | double Latitude; // degrees 529 | double Longitude; // degrees 530 | double Altitude; // meters 531 | }; 532 | 533 | // SIMCONNECT_RECV_AIRPORT_LIST 534 | struct SIMCONNECT_RECV_AIRPORT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 535 | { 536 | SIMCONNECT_DATA_FACILITY_AIRPORT rgData[1]; 537 | }; 538 | 539 | 540 | // SIMCONNECT_DATA_FACILITY_WAYPOINT 541 | struct SIMCONNECT_DATA_FACILITY_WAYPOINT : public SIMCONNECT_DATA_FACILITY_AIRPORT 542 | { 543 | float fMagVar; // Magvar in degrees 544 | }; 545 | 546 | // SIMCONNECT_RECV_WAYPOINT_LIST 547 | struct SIMCONNECT_RECV_WAYPOINT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 548 | { 549 | SIMCONNECT_DATA_FACILITY_WAYPOINT rgData[1]; 550 | }; 551 | 552 | // SIMCONNECT_DATA_FACILITY_NDB 553 | struct SIMCONNECT_DATA_FACILITY_NDB : public SIMCONNECT_DATA_FACILITY_WAYPOINT 554 | { 555 | DWORD fFrequency; // frequency in Hz 556 | }; 557 | 558 | // SIMCONNECT_RECV_NDB_LIST 559 | struct SIMCONNECT_RECV_NDB_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 560 | { 561 | SIMCONNECT_DATA_FACILITY_NDB rgData[1]; 562 | }; 563 | 564 | // SIMCONNECT_DATA_FACILITY_VOR 565 | struct SIMCONNECT_DATA_FACILITY_VOR : public SIMCONNECT_DATA_FACILITY_NDB 566 | { 567 | DWORD Flags; // SIMCONNECT_VOR_FLAGS 568 | float fLocalizer; // Localizer in degrees 569 | double GlideLat; // Glide Slope Location (deg, deg, meters) 570 | double GlideLon; 571 | double GlideAlt; 572 | float fGlideSlopeAngle; // Glide Slope in degrees 573 | }; 574 | 575 | // SIMCONNECT_RECV_VOR_LIST 576 | struct SIMCONNECT_RECV_VOR_LIST : public SIMCONNECT_RECV_FACILITIES_LIST 577 | { 578 | SIMCONNECT_DATA_FACILITY_VOR rgData[1]; 579 | }; 580 | # 632 "SimConnect.h" 581 | // SIMCONNECT_DATATYPE_INITPOSITION 582 | struct SIMCONNECT_DATA_INITPOSITION 583 | { 584 | double Latitude; // degrees 585 | double Longitude; // degrees 586 | double Altitude; // feet 587 | double Pitch; // degrees 588 | double Bank; // degrees 589 | double Heading; // degrees 590 | DWORD OnGround; // 1=force to be on the ground 591 | DWORD Airspeed; // knots 592 | }; 593 | 594 | 595 | // SIMCONNECT_DATATYPE_MARKERSTATE 596 | struct SIMCONNECT_DATA_MARKERSTATE 597 | { 598 | char szMarkerName[64]; 599 | DWORD dwMarkerState; 600 | }; 601 | 602 | // SIMCONNECT_DATATYPE_WAYPOINT 603 | struct SIMCONNECT_DATA_WAYPOINT 604 | { 605 | double Latitude; // degrees 606 | double Longitude; // degrees 607 | double Altitude; // feet 608 | unsigned long Flags; 609 | double ktsSpeed; // knots 610 | double percentThrottle; 611 | }; 612 | 613 | // SIMCONNECT_DATA_LATLONALT 614 | struct SIMCONNECT_DATA_LATLONALT 615 | { 616 | double Latitude; 617 | double Longitude; 618 | double Altitude; 619 | }; 620 | 621 | // SIMCONNECT_DATA_XYZ 622 | struct SIMCONNECT_DATA_XYZ 623 | { 624 | double x; 625 | double y; 626 | double z; 627 | }; 628 | 629 | #pragma pack(pop) 630 | 631 | //---------------------------------------------------------------------------- 632 | // End of Struct definitions 633 | //---------------------------------------------------------------------------- 634 | 635 | typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); 636 | # 703 "SimConnect.h" 637 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName = ""); 638 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags); 639 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetSystemEventState(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_STATE dwState); 640 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AddClientEventToNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable = FALSE); 641 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RemoveClientEvent(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID); 642 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetNotificationGroupPriority(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); 643 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_ClearNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID); 644 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD dwReserved = 0, DWORD Flags = 0); 645 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * DatumName, const char * UnitsName, SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); 646 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_ClearDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); 647 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); 648 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestDataOnSimObjectType(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, DWORD dwRadiusMeters, SIMCONNECT_SIMOBJECT_TYPE type); 649 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); 650 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MapInputEventToClientEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); 651 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetInputGroupPriority(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD uPriority); 652 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RemoveInputEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition); 653 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_ClearInputGroup(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID); 654 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetInputGroupState(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD dwState); 655 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestReservedKey(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * szKeyChoice1 = "", const char * szKeyChoice2 = "", const char * szKeyChoice3 = ""); 656 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); 657 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_UnsubscribeFromSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); 658 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRequestInterpolatedObservation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt); 659 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRequestObservationAtStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 660 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRequestObservationAtNearestStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon); 661 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherCreateStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO, const char * szName, float lat, float lon, float alt); 662 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRemoveStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 663 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char * szMETAR); 664 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetModeServer(HANDLE hSimConnect, DWORD dwPort, DWORD dwSeconds); 665 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetModeTheme(HANDLE hSimConnect, const char * szThemeName); 666 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect); 667 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetModeCustom(HANDLE hSimConnect); 668 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherSetDynamicUpdateRate(HANDLE hSimConnect, DWORD dwRate); 669 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRequestCloudState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float minLat, float minLon, float minAlt, float maxLat, float maxLon, float maxAlt, DWORD dwFlags = 0); 670 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherCreateThermal(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt, float radius, float height, float coreRate = 3.0f, float coreTurbulence = 0.05f, float sinkRate = 3.0f, float sinkTurbulence = 0.2f, float coreSize = 0.4f, float coreTransitionSize = 0.1f, float sinkLayerSize = 0.4f, float sinkTransitionSize = 0.1f); 671 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_WeatherRemoveThermal(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID); 672 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); 673 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); 674 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 675 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char * szContainerTitle, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 676 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 677 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 678 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AISetAircraftFlightPlan(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, const char * szFlightPlanPath, SIMCONNECT_DATA_REQUEST_ID RequestID); 679 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_ExecuteMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 680 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_CompleteCustomMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 681 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_Close(HANDLE hSimConnect); 682 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RetrieveString(SIMCONNECT_RECV * pData, DWORD cbData, void * pStringV, char ** pszString, DWORD * pcbString); 683 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD * pdwError); 684 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); 685 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); 686 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData); 687 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestResponseTimes(HANDLE hSimConnect, DWORD nCount, float * fElapsedSeconds); 688 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_InsertString(char * pDest, DWORD cbDest, void ** ppEnd, DWORD * pcbStringV, const char * pSource); 689 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_CameraSetRelative6DOF(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg); 690 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MenuAddItem(HANDLE hSimConnect, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, DWORD dwData); 691 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MenuDeleteItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID); 692 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MenuAddSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID, DWORD dwData); 693 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MenuDeleteSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID); 694 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestSystemState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szState); 695 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetSystemState(HANDLE hSimConnect, const char * szState, DWORD dwInteger, float fFloat, const char * szString); 696 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char * szClientDataName, SIMCONNECT_CLIENT_DATA_ID ClientDataID); 697 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags); 698 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwOffset, DWORD dwSizeOrType, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); 699 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_ClearClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID); 700 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_PERIOD Period = SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); 701 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_SET_FLAG Flags, DWORD dwReserved, DWORD cbUnitSize, void * pDataSet); 702 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_FlightLoad(HANDLE hSimConnect, const char * szFileName); 703 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_FlightSave(HANDLE hSimConnect, const char * szFileName, const char * szTitle, const char * szDescription, DWORD Flags); 704 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_FlightPlanLoad(HANDLE hSimConnect, const char * szFileName); 705 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_Text(HANDLE hSimConnect, SIMCONNECT_TEXT_TYPE type, float fTimeSeconds, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD cbUnitSize, void * pDataSet); 706 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_SubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); 707 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_UnsubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type); 708 | extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_RequestFacilitiesList(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); 709 | -------------------------------------------------------------------------------- /scripts/float.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/scripts/float.h -------------------------------------------------------------------------------- /scripts/genscdefs.py: -------------------------------------------------------------------------------- 1 | # Generate SimConnect_cpp.h via: 2 | # 3 | # touch float.h 4 | # cpp -nostdinc -I. -CC SimConnect.h > SimConnect_cpp.h 5 | # 6 | import re 7 | from typing import List 8 | 9 | 10 | def nopfx(s: str, pfx='SIMCONNECT_') -> str: 11 | return s.replace(pfx, '') 12 | 13 | 14 | def _ctyp(typ): 15 | ctyp = nopfx(typ).strip() 16 | if ctyp.startswith('const'): 17 | ctyp = ctyp[5:].strip() 18 | if ctyp.startswith('BOOL'): 19 | ctyp = 'bool' + ctyp[4:] 20 | m = re.match(r'([a-z]+(?:\s+\*)?)(.*)', ctyp) 21 | if m: 22 | t, suffix = m.groups() 23 | ctyp = 'c_' + re.sub(r'\s+', '_', t.replace('*', 'p')) + suffix 24 | stars = 0 25 | while True: 26 | ctyp = ctyp.strip() 27 | if ctyp[-1] != '*': 28 | break 29 | stars += 1 30 | ctyp = ctyp[:-1] 31 | for _ in range(stars): 32 | ctyp = f"POINTER({ctyp})" 33 | return ctyp 34 | 35 | 36 | # typedef DWORD SIMCONNECT_WAYPOINT_FLAGS; 37 | def maybeTypedef(line, lines, output) -> bool: 38 | # special case for DispatchProc 39 | # typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); 40 | if line.startswith('typedef void') and 'DispatchProc' in line: 41 | output += [ 42 | '# ' + line, 43 | 'DispatchProc = WINFUNCTYPE(None, POINTER(RECV), DWORD, c_void_p)', 44 | ] 45 | return True 46 | 47 | m = re.match(r'typedef\s+(\w+)\s+(\w+)\s*;(.*)', line) 48 | if not m: 49 | return False 50 | 51 | typ, aka, suffix = m.groups() 52 | aka = nopfx(aka) 53 | output.append(f"{aka} = {typ} {suffix}") 54 | return True 55 | 56 | 57 | # static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority 58 | def maybeConst(line, lines, output, indent='') -> bool: 59 | m = re.match(r'\s*static\s+const\s+(\w+)\s+(\w+)\s*=\s*(\S+);(.*)', line) 60 | if not m: 61 | return False 62 | 63 | typ, var, val, suffix = m.groups() 64 | var = nopfx(var) 65 | val = nopfx(val) 66 | if typ not in ['float', 'DWORD']: 67 | val = f"{typ}({val})" 68 | line = f"{var} = {val} {suffix}" 69 | output.append(indent + line) 70 | return True 71 | 72 | 73 | # enum SIMCONNECT_RECV_ID { 74 | def maybeEnum(line, lines, output) -> bool: 75 | """convert enums into python int consts, with a type alias to DWORD""" 76 | m = re.match(r'\s*enum\s+(\w+)\s*{(.*)', line) 77 | if not m: 78 | return False 79 | 80 | enum, suffix = m.groups() 81 | enum = nopfx(enum) 82 | line = f"{enum} = DWORD" # type alias for function decls 83 | eidx = -1 84 | output.append(line) 85 | 86 | while True: 87 | line = lines.pop(0) 88 | if line.strip().startswith('};'): 89 | break 90 | # SIMCONNECT_TEXT_TYPE_PRINT_BLACK=0x0100, 91 | m = re.match(r'\s*(\w+)(?:\s*=\s*([0-9x]*))?(?:\s*,)?(.*)', line) 92 | if m: 93 | var, val, suffix = m.groups() 94 | var = nopfx(var) 95 | if val is None: 96 | eidx += 1 97 | else: 98 | eidx = eval(val) 99 | line = f"{var} = 0x{eidx:02X} {suffix}" 100 | output.append(line) 101 | output.append('') 102 | return True 103 | 104 | 105 | # unsigned long Flags; // ... 106 | def maybeField(line, lines, fields) -> bool: 107 | m = re.match(r'\s*(?:(\w+)\s+)+(\w+)(\[\w+\])?\s*;(.*)', line) 108 | if not m: 109 | return False 110 | 111 | typ, field, size, suffix = m.groups() 112 | typ = _ctyp(typ) 113 | if size: 114 | typ = f"{typ} * {size.strip('[]')}" 115 | line = f'("{field}", {typ}), {suffix}' 116 | fields.append(line) 117 | return True 118 | 119 | 120 | # struct SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION 121 | def maybeStruct(line, lines, output) -> bool: 122 | m = re.match(r'\s*struct\s+(\w+)\s*(?::\s*public\s+(\w+))?(.*)', line) 123 | if not m: 124 | return False 125 | 126 | struct, base, suffix = m.groups() 127 | struct = nopfx(struct) 128 | base = nopfx(base) if base else 'Struct1' 129 | line = f"class {struct}({base}):" 130 | output.append(line) 131 | fields: List[str] = [] 132 | 133 | while True: 134 | line = lines.pop(0) 135 | if line.startswith('{'): 136 | continue 137 | elif line.startswith('};'): 138 | break 139 | elif maybeConst(line, lines, output, indent): 140 | continue 141 | elif maybeField(line, lines, fields): 142 | continue 143 | else: 144 | output.append(line.strip()) 145 | 146 | output.append(indent + '_fields_ = [') 147 | for line in fields: 148 | output.append(2 * indent + line) 149 | output.append(indent + ']') 150 | output.append('') 151 | return True 152 | 153 | 154 | # extern "C" HRESULT __attribute__((__stdcall__)) SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, ... 155 | def maybeDecl(line, lines, decls) -> bool: 156 | m = re.match(r'extern\s+"C"\s+(.*?)\s+__attribute__\(\(__stdcall__\)\)\s+(\w+)\((.*?)\)', line) 157 | if not m: 158 | return False 159 | 160 | ret, func, arglist = m.groups() 161 | args = arglist.split(',') 162 | 163 | decls += [ 164 | f"f = dll.{func}", 165 | f"f.restype = {ret}", 166 | "f.argtypes = [", 167 | ] 168 | for arg in args: 169 | m = re.match(r'(.*?)\s+(\w+)(?:\s*=\s*(.*))?$', arg.strip()) 170 | assert m, f"Unrecognized arg {arg}" 171 | typ, var, dflt = m.groups() 172 | dflt = f"= {dflt.strip()}" if dflt else "" 173 | decls.append(f"{indent}{_ctyp(typ)}, # {typ} {var} {dflt}") 174 | decls += [ 175 | "]", 176 | f"_['{func.replace('SimConnect_', '')}'] = f", 177 | ] 178 | return True 179 | 180 | 181 | indent = ' ' * 4 182 | 183 | lines = open('SimConnect_cpp.h').read().splitlines() 184 | lines = [ 185 | re.sub( 186 | r'(\s*)//\s*', 187 | lambda m: ' # ' if m.group(1) else '# ', 188 | line, 189 | 1) 190 | for line in lines 191 | ] 192 | 193 | output: List[str] = [] 194 | aka = None 195 | eidx = None 196 | decls = [ 197 | '_ = dict()', 198 | ] 199 | while lines: 200 | line = lines.pop(0) 201 | 202 | if maybeTypedef(line, lines, output): 203 | continue 204 | elif maybeConst(line, lines, output): 205 | continue 206 | elif maybeEnum(line, lines, output): 207 | continue 208 | elif maybeStruct(line, lines, output): 209 | continue 210 | elif maybeDecl(line, lines, decls): 211 | continue 212 | else: 213 | output.append(line) 214 | 215 | decls += [ 216 | 'return _', 217 | ] 218 | 219 | output += [ 220 | '', 221 | '', 222 | 'def _decls(dll):', 223 | ] + [indent + s for s in decls] 224 | 225 | with open('simconnect/scdefs.py', 'w') as out: 226 | out.write("""# 227 | # DO NOT EDIT: Auto generated by genscdefs.py 228 | # 229 | from ctypes import ( 230 | c_bool, c_char, c_int, c_long, c_float, c_double, 231 | c_char_p, c_void_p, 232 | Structure, POINTER, 233 | ) 234 | try: 235 | from ctypes import HRESULT, WINFUNCTYPE, windll 236 | from ctypes.wintypes import BYTE, WORD, DWORD, HANDLE, LPCSTR, HWND 237 | except: 238 | from .winstubs import HRESULT, WINFUNCTYPE, windll 239 | from .winstubs import BYTE, WORD, DWORD, HANDLE, LPCSTR, HWND 240 | 241 | 242 | c_float_p = POINTER(c_float) 243 | FLT_MAX = 3.402823466e+38 244 | MAX_PATH = 260 245 | 246 | 247 | class GUID(Structure): 248 | _fields_ = [ 249 | ("Data1", DWORD), 250 | ("Data2", WORD), 251 | ("Data3", WORD), 252 | ("Data4", BYTE * 8) 253 | ] 254 | 255 | 256 | class Struct1(Structure): 257 | _pack_ = 1 # implement the pragma(push, 1) 258 | 259 | 260 | """) 261 | out.write('\n'.join([s.rstrip() for s in output]) + '\n') 262 | -------------------------------------------------------------------------------- /scripts/mkidx.py: -------------------------------------------------------------------------------- 1 | from lunr import lunr 2 | from lunr.index import Index 3 | import json 4 | import os 5 | 6 | 7 | tgtdir = os.path.join(os.path.dirname(__file__), '../simconnect') 8 | 9 | with open(os.path.join(tgtdir, 'scvars.json')) as f: 10 | scvars = json.load(f) 11 | 12 | docs = [ 13 | dict( 14 | id=f"{kind}_{key}", 15 | kind=kind, 16 | # index the name without underscores 17 | name=d['name'].replace('_', ' '), 18 | name_=d['name'].replace(' ', '_'), 19 | page=d['page'], 20 | section=d['section'], 21 | description=d.get('description', ''), 22 | ) 23 | for kind, instances in scvars.items() 24 | for key, d in instances.items() 25 | if kind != 'DIMENSIONS' 26 | ] 27 | 28 | idx = lunr( 29 | ref='id', 30 | fields=['kind', 'name', 'name_', 'description', 'page', 'section'], 31 | documents=docs 32 | ) 33 | 34 | idxpath = os.path.join(tgtdir, 'scvars_idx.json') 35 | with open(idxpath, 'w') as f: 36 | json.dump(idx.serialize(), f) 37 | 38 | with open(idxpath) as f: 39 | idx = Index.load(json.load(f)) 40 | 41 | results = idx.search('+kind:EVENTS alti*')[:5] 42 | print(results) 43 | for r in results: 44 | kind, key = r['ref'].split('_', 1) 45 | print(kind, key, scvars[kind][key].get('description')) 46 | -------------------------------------------------------------------------------- /scripts/prepvars.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | import re 4 | from typing import Dict 5 | from simconnect.scvars import _unitstd, _namestd, _eventstd 6 | 7 | 8 | def prepvars(src: Dict) -> Dict: 9 | prep: Dict[str, Dict[str, Dict]] = dict( 10 | DIMENSIONS={}, 11 | UNITS={}, 12 | VARIABLES={}, 13 | EVENTS={}, 14 | ) 15 | # build a list of all recognized units, seed with a few not mentioned in UNITS table 16 | all_units = { 17 | '_': '', 18 | } 19 | for d in src['UNITS']: 20 | # don't preprocess all the base unit names 21 | names = _unitstd(d['name'], False) 22 | us = _unitstd(d['name']) 23 | for (name, u) in zip(names, us): 24 | all_units[u] = name 25 | prep['UNITS'][u] = dict(d, name_std=name, dimensions=d.get('section', '')) 26 | for v in prep['UNITS'].values(): 27 | prep['DIMENSIONS'].setdefault(v['dimensions'], []).append(v['name_std']) 28 | for d in src['VARIABLES']: 29 | # skip some extraneous tables we scraped 30 | if 'RTPC' in d['page'] or re.match(r'\d+', d['name']): 31 | continue 32 | if '\n' in d['name']: 33 | parts = [s.strip() for s in d['name'].split('\n', 1)] 34 | d['name'] = parts[0] 35 | d['description'] = d.get('description', '') + ' ' + parts[1] 36 | k = _namestd(d['name']) 37 | d['name_std'] = k 38 | if 'units' not in d: 39 | logging.warning(f"Simvar {d['name']} lacks units") 40 | u = '' 41 | else: 42 | u = _unitstd(d['units'])[-1] 43 | if u not in all_units: 44 | logging.warning(f"Simvar {d['name']} has unrecognized unit '{u}'") 45 | ustd = all_units.get(u, '') 46 | d['units_std'] = ustd 47 | # get a list of all canonical units with matching dimensions 48 | d['dimensions'] = prep['UNITS'].get(u, {}).get('dimensions', '') 49 | d['indexed'] = ':' in d['name'] 50 | prep['VARIABLES'][k] = d 51 | for d in src['EVENTS']: 52 | if '\n' in d['name']: 53 | parts = [s.strip() for s in d['name'].split('\n', 1)] 54 | d['name'] = parts[0] 55 | d['description'] = d.get('description', '') + ' ' + parts[1] 56 | k = _eventstd(d['name']) 57 | d['name_std'] = k 58 | prep['EVENTS'][k] = d 59 | 60 | return prep 61 | 62 | 63 | if __name__ == '__main__': 64 | import os 65 | thisdir = os.path.dirname(__file__) 66 | scvars_json = os.path.join(thisdir, 'scvars_raw.json') 67 | scvars_prep_json = os.path.join(thisdir, 'scvars_prep.json') 68 | 69 | src = json.load(open(scvars_json)) 70 | prep = prepvars(src) 71 | json.dump(prep, open(scvars_prep_json, 'w'), indent=4) 72 | -------------------------------------------------------------------------------- /scripts/scrapevars.py: -------------------------------------------------------------------------------- 1 | # Grab tables of variables from the SDK docs 2 | # 3 | # Run via: 4 | # 5 | # scrapy runspider scripts/scrapevars.py --nolog -O simconnect/scvars.json 6 | # 7 | import scrapy 8 | import scrapy.exporters 9 | import unicodedata 10 | import json 11 | from prepvars import prepvars 12 | 13 | 14 | base_urls = [ 15 | # main list of links 16 | 'https://docs.flightsimulator.com/html/Programming_Tools/SimVars/Simulation_Variables.htm', 17 | # not linked explicitly elsewhere 18 | 'https://docs.flightsimulator.com/html/Programming_Tools/SimVars/Event_IDs/Aircraft_Electrical_Events.htm' 19 | ] 20 | 21 | 22 | def normtext(s): 23 | return unicodedata.normalize('NFKC', s) if s else '' 24 | 25 | 26 | def jointext(xs): 27 | return ''.join(map(normtext, xs.getall())).strip() 28 | 29 | 30 | class PostProcessExporter(scrapy.exporters.BaseItemExporter): 31 | def __init__(self, file, **kwargs): 32 | super().__init__(dont_fail=True, **kwargs) 33 | self.file = file 34 | self.items = [] 35 | 36 | def start_exporting(self): 37 | pass 38 | 39 | def export_item(self, item): 40 | self.items.append(item) 41 | 42 | def finish_exporting(self): 43 | raw = dict() 44 | for item in sorted(self.items, key=lambda d: (d['page'], d['index'])): 45 | typ = item['type'] 46 | del item['type'] 47 | del item['index'] 48 | raw.setdefault(typ, []).append(item) 49 | output = prepvars(raw) 50 | s = json.dumps(output, indent=4).encode('utf-8') 51 | self.file.write(s) 52 | 53 | 54 | class SimConnectSpider(scrapy.Spider): 55 | name = "SimConnectSDK" 56 | 57 | custom_settings = { 58 | 'FEED_EXPORTERS': {'json': PostProcessExporter} 59 | } 60 | 61 | def start_requests(self): 62 | for url in base_urls: 63 | yield scrapy.Request(url, callback=self.parse) 64 | 65 | def parse(self, response): 66 | def alltext(elt): 67 | if elt: 68 | return jointext(elt.xpath('.//text()')) 69 | else: 70 | return None 71 | 72 | def parse_row(row, simvar): 73 | tds = row.xpath('td') 74 | ncol = len(tds) 75 | if ncol < 2: 76 | return None 77 | # simvar tables have 4 or 5 cols, with last two being units and settable 78 | # sometimes omitting multiplayer, 79 | # other tables have two or three cols 80 | labels = ['name', 'description', 'multiplayer', 'units', 'settable'] 81 | vs = [ 82 | jointext(tds[0].xpath('.//text()')) 83 | ] + [ 84 | alltext(td) for td in tds[1:(ncol-1 if simvar else ncol)] 85 | ] 86 | if simvar: 87 | vs.append(tds.xpath('span[@class="checkmark"]/span/@class').get() == 'checkmark_circle') 88 | if ncol < 5: 89 | # always keep last two cols 90 | labels = labels[:ncol-2] + labels[-2:] 91 | return dict(zip(labels, vs)) 92 | 93 | # look for nested pages 94 | urls = response.xpath('//div//ul/li/a/@href').getall() 95 | for url in urls: 96 | yield scrapy.Request(url=response.urljoin(url), callback=self.parse) 97 | 98 | page = normtext(response.xpath('//h2/text()').get()).strip() 99 | context = { 100 | 'url': response.url, 101 | 'page': page, 102 | 'type': page.split()[-1].replace('IDs', 'EVENTS') 103 | } 104 | i = 0 105 | for tbl in response.xpath('//table'): 106 | section = tbl.xpath('preceding-sibling::h4[1]') or tbl.xpath('preceding-sibling::h3[1]') 107 | context['section'] = normtext(section.xpath('text()').get()) 108 | simvar = tbl.xpath('tbody/tr/th/text()').get().strip().lower() == 'simulation variable' 109 | for row in tbl.xpath('tbody/tr'): 110 | d = parse_row(row, simvar) 111 | if d: 112 | d.update(context, index=i) 113 | i += 1 114 | yield d 115 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = pysimconnect 3 | version = 0.2.6 4 | author = Patrick Surry 5 | author_email = patrick.surry@gmail.com 6 | description = Python wrapper for Microsoft FlightSimulator 2020 SimConnect SDK 7 | long_description = file: README.md 8 | long_description_content_type = text/markdown 9 | keywords = pysimconnect, SimConnect, SimVars, ctypes, SDK, API, FS2020, Microsoft Flight Simulator 10 | url = https://github.com/patricksurry/pysimconnect 11 | project_urls = 12 | Bug Tracker = https://github.com/patricksurry/pysimconnect/issues 13 | classifiers = 14 | Programming Language :: Python :: 3 15 | License :: OSI Approved :: MIT License 16 | Operating System :: OS Independent 17 | 18 | [options] 19 | packages = simconnect 20 | python_requires = >=3.6 21 | install_requires = 22 | typer >= 0.9 23 | click >= 8.1 24 | lunr 25 | 26 | [options.entry_points] 27 | console_scripts = 28 | simconnect = simconnect.cli:app [typer] 29 | 30 | [options.package_data] 31 | * = scvars*.json, SimConnect.dll 32 | -------------------------------------------------------------------------------- /simconnect/SimConnect.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patricksurry/pysimconnect/fc6b73e401d27517ca8b45a8af1c3ee85bed5b2d/simconnect/SimConnect.dll -------------------------------------------------------------------------------- /simconnect/__init__.py: -------------------------------------------------------------------------------- 1 | from .scdefs import * 2 | from .sc import SimConnect, RECV_P 3 | from .receiver import Receiver, ReceiverInstance 4 | from .datadef import SimData, SimDataHandler , DataDefinition 5 | from .scvars import SIMVARS, EVENTS, UNITS, DIMENSIONS 6 | -------------------------------------------------------------------------------- /simconnect/_typerpatch.py: -------------------------------------------------------------------------------- 1 | # Provides powershell fix from https://github.com/tiangolo/typer/pull/360 until new typer release 2 | 3 | from typing import List, Tuple 4 | import click 5 | import os 6 | from typer import _completion_shared 7 | from typer._compat_utils import _get_click_major 8 | 9 | 10 | if '_TYPER_CURSOR_POSITION' not in _completion_shared.COMPLETION_SCRIPT_POWER_SHELL: 11 | _pwsh_script = """ 12 | Import-Module PSReadLine 13 | Set-PSReadLineKeyHandler -Chord Tab -Function MenuComplete 14 | $scriptblock = { 15 | param($wordToComplete, $commandAst, $cursorPosition) 16 | $Env:%(autocomplete_var)s = "complete_powershell" 17 | $Env:_TYPER_COMPLETE_ARGS = $commandAst.ToString() 18 | $Env:_TYPER_COMPLETE_WORD_TO_COMPLETE = $wordToComplete 19 | $Env:_TYPER_CURSOR_POSITION = $cursorPosition 20 | %(prog_name)s | ForEach-Object { 21 | $commandArray = $_ -Split ":::" 22 | $command = $commandArray[0] 23 | $helpString = $commandArray[1] 24 | [System.Management.Automation.CompletionResult]::new( 25 | $command, $command, 'ParameterValue', $helpString) 26 | } 27 | $Env:%(autocomplete_var)s = "" 28 | $Env:_TYPER_COMPLETE_ARGS = "" 29 | $Env:_TYPER_COMPLETE_WORD_TO_COMPLETE = "" 30 | $Env:_TYPER_CURSOR_POSITION = "" 31 | } 32 | Register-ArgumentCompleter -Native -CommandName %(prog_name)s -ScriptBlock $scriptblock 33 | """ 34 | 35 | _completion_shared.COMPLETION_SCRIPT_POWER_SHELL = _pwsh_script 36 | for k in ('pwsh', 'powershell'): 37 | _completion_shared._completion_scripts[k] = _pwsh_script 38 | 39 | if _get_click_major() < 8: 40 | from typer import _completion_click7 41 | 42 | def do_powershell_complete(cli: click.Command, prog_name: str) -> bool: 43 | completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") 44 | incomplete = os.getenv("_TYPER_COMPLETE_WORD_TO_COMPLETE", "") 45 | cursor = os.getenv("_TYPER_CURSOR_POSITION") 46 | if cursor: 47 | completion_args = completion_args[:int(cursor)] 48 | cwords = click.parser.split_arg_string(completion_args) 49 | args = cwords[1:-1] if incomplete else cwords[1:] 50 | for item, help in click._bashcomplete.get_choices(cli, prog_name, args, incomplete): 51 | click.echo(f"{item}:::{help or ' '}") 52 | 53 | return True 54 | 55 | _completion_click7.do_powershell_complete = do_powershell_complete 56 | 57 | else: 58 | from typer import _completion_click8 59 | 60 | def get_completion_args(self) -> Tuple[List[str], str]: 61 | completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") 62 | incomplete = os.getenv("_TYPER_COMPLETE_WORD_TO_COMPLETE", "") 63 | cursor = os.getenv("_TYPER_CURSOR_POSITION") 64 | if cursor: 65 | completion_args = completion_args[:int(cursor)] 66 | cwords = click.parser.split_arg_string(completion_args) 67 | args = cwords[1:-1] if incomplete else cwords[1:] 68 | return args, incomplete 69 | 70 | _completion_click8.PowerShellComplete.get_completion_args = get_completion_args 71 | -------------------------------------------------------------------------------- /simconnect/changedict.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | from time import time 3 | import math 4 | from typing import Callable, Any 5 | from itertools import takewhile 6 | 7 | 8 | def now(): 9 | return round(time() * 1000) 10 | 11 | 12 | def equal_or_close(rel_tol=1e-6, abs_tol=1e-6) -> Callable[[Any, Any], bool]: 13 | """Return a function that decides if a ~= b""" 14 | def comparator(a, b) -> bool: 15 | try: 16 | v = math.isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) 17 | except Exception: 18 | v = a == b 19 | return v 20 | return comparator 21 | 22 | 23 | class ChangeDict(OrderedDict): 24 | """An ordered dict that records timestamp of changed items""" 25 | def __init__(self, default_comparator=equal_or_close(), comparators={}): 26 | self.__default_comparator = default_comparator 27 | self.__comparators = comparators 28 | self.__times = {} 29 | 30 | def __setitem__(self, k, v): 31 | if k in self: 32 | vv = self[k] 33 | eq = self.__comparators.get(k, self.__default_comparator) 34 | if eq(v, vv): 35 | return 36 | super().__setitem__(k, v) 37 | self.move_to_end(k) 38 | self.__times[k] = now() 39 | 40 | def __delitem__(self, k, v): 41 | super().__delitem__(k, v) 42 | del self.__times[k] 43 | 44 | def latest(self): 45 | if not self.__times: 46 | return 0 47 | k = next(reversed(self)) 48 | return self.__times[k] 49 | 50 | def changedsince(self, millis): 51 | return dict( 52 | takewhile( 53 | lambda kv: self.__times[kv[0]] > millis, 54 | reversed(self.items()) 55 | ) 56 | ) 57 | 58 | 59 | if __name__ == '__main__': 60 | from time import sleep 61 | 62 | t = now() 63 | d = ChangeDict(comparators=dict(froz=lambda a, b: abs(a-b) < 8)) 64 | d.update(a=1, b=2, z='zzz', froz=1024) 65 | print(d.changedsince(0), d.latest()) 66 | sleep(1) 67 | d.update(a=1, b=3, c=3, froz=1031) 68 | print(d.changedsince(t), d.latest()) 69 | sleep(1) 70 | d.update(a=4, froz=1033) 71 | print(d.changedsince(t+1500), d.latest()) 72 | print(d) 73 | -------------------------------------------------------------------------------- /simconnect/cli.py: -------------------------------------------------------------------------------- 1 | import typer 2 | from . import _typerpatch 3 | import json 4 | from typing import List, Optional 5 | from textwrap import fill 6 | from enum import Enum 7 | from lunr.index import Index 8 | from simconnect import SimConnect 9 | import os 10 | import re 11 | 12 | 13 | app = typer.Typer() 14 | 15 | thisdir = os.path.dirname(__file__) 16 | with open(os.path.join(thisdir, 'scvars.json')) as f: 17 | scvars = json.load(f) 18 | for k in ['EVENTS', 'VARIABLES', 'UNITS']: 19 | for d in scvars[k].values(): 20 | d['name_'] = d['name' if k != 'UNITS' else 'name_std'].replace(' ', '_') 21 | 22 | 23 | class MetadataKind(str, Enum): 24 | variable = 'variable' 25 | event = 'event' 26 | unit = 'unit' 27 | 28 | 29 | def floatfmt(v, width=12, precision=3): 30 | s = f"{v:{width}.{precision}f}".rstrip('0').rstrip('.') 31 | s += ' ' * (width - len(s)) 32 | return s 33 | 34 | 35 | def labelfmt(s, width=2*12): 36 | label = s if len(s) < width else s[:width-4] + '...' 37 | return f"{label:{width}s}" 38 | 39 | 40 | def matchcase(s: str, prefix: str) -> Optional[str]: 41 | if not prefix: 42 | return s 43 | elif not s.upper().startswith(prefix.upper()): 44 | return None 45 | elif len(prefix) == len(s): 46 | return prefix 47 | else: 48 | tail = s[len(prefix):] 49 | return prefix + (tail.upper() if prefix[-1].isupper() else tail.lower()) 50 | 51 | 52 | def scoped_autocomplete(kind: str, max_results=10): 53 | def _complete(incomplete: str): 54 | return sorted( 55 | list(filter(None, (matchcase(d['name_'], incomplete) for d in scvars[kind].values()))), 56 | key=lambda s: (len(s), s) 57 | )[:max_results] 58 | return _complete 59 | 60 | 61 | simvardef = typer.Argument(..., autocompletion=scoped_autocomplete('VARIABLES')) 62 | eventdef = typer.Argument(..., autocompletion=scoped_autocomplete('EVENTS')) 63 | unitsdef = typer.Option(None, autocompletion=scoped_autocomplete('UNITS')) 64 | 65 | 66 | def canonicalvars(simvars: List[str]) -> List[str]: 67 | # appear to be case insenstive but ' ' vs '_' is important 68 | return [s.upper().replace('_', ' ') for s in simvars] 69 | 70 | 71 | @app.command() 72 | def get(simvars: List[str] = simvardef, units: Optional[str] = unitsdef): 73 | simvars = canonicalvars(simvars) 74 | unitdesc = f" ({units})" if units else '' 75 | for s in simvars: 76 | with SimConnect(name='cli') as sc: 77 | v = sc.get_simdatum(s.replace('_,', ' '), units) 78 | typer.echo(f"{s}{unitdesc} = {v}") 79 | 80 | 81 | @app.command() 82 | def watch(simvars: List[str] = simvardef, units: Optional[str] = unitsdef, interval: Optional[int] = 1): 83 | simvars = canonicalvars(simvars) 84 | typer.echo(f"Watching {', '.join(simvars)} every {interval} seconds") 85 | with SimConnect(name='cli') as sc: 86 | dd = sc.subscribe_simdata( 87 | [dict(name=sv, units=units) for sv in simvars], 88 | interval=interval 89 | ) 90 | latest = 0 91 | headings = None 92 | while True: 93 | # consume incoming messages, waiting up to a second 94 | sc.receive(timeout_seconds=1) 95 | if not headings: 96 | # show staggered header across two lines 97 | headings = list(dd.simdata.keys()) 98 | # even cols 99 | typer.echo(''.join(labelfmt(headings[i]) for i in range(0, len(headings), 2))) 100 | # odd cols 101 | typer.echo(' '*12 + ''.join(labelfmt(headings[i]) for i in range(1, len(headings), 2))) 102 | changed = list(dd.simdata.changedsince(latest).keys()) 103 | latest = dd.simdata.latest() 104 | values = [ 105 | typer.style( 106 | floatfmt(dd.simdata[k]), 107 | fg=typer.colors.BLUE if k in changed else typer.colors.WHITE 108 | ) 109 | for k in headings 110 | ] 111 | typer.echo(''.join(values)) 112 | 113 | 114 | @app.command() 115 | def set(simvar: str = simvardef, value: float = typer.Argument(...), units: Optional[str] = unitsdef): 116 | simvar = canonicalvars([simvar])[0] 117 | typer.echo(f"Setting {simvar} = {value}" + (f" ({units})" if units else '')) 118 | with SimConnect(name='cli') as sc: 119 | sc.set_simdatum(simvar, value, units) 120 | 121 | 122 | @app.command() 123 | def send(event: str = eventdef, value: Optional[float] = None): 124 | event = event.upper() 125 | typer.echo(f"Sending {event}({value})") 126 | with SimConnect(name='cli') as sc: 127 | sc.send_event(event, value or 0) 128 | 129 | 130 | @app.command() 131 | def search(name: List[str], kind: Optional[MetadataKind] = None, max_results: int = 10, brief: bool = False): 132 | q = ' '.join(name) 133 | if kind: 134 | q += f" +kind:{kind.name.upper()}S" 135 | 136 | with open(os.path.join(thisdir, 'scvars_idx.json')) as f: 137 | scvarsidx = Index.load(json.load(f)) 138 | 139 | styles = dict( 140 | # in mac terminal some double-width emoji need a trailing space to display correctly 141 | # but this seems fine on windows terminal 142 | VARIABLES=dict(color=typer.colors.BLUE, symbol="🧭"), 143 | EVENTS=dict(color=typer.colors.GREEN, symbol="⚙️"), # or maybe? 🔔 144 | UNITS=dict(color=typer.colors.RED, symbol="📐"), 145 | DIMENSIONS=dict(color=typer.colors.MAGENTA, symbol="📏"), 146 | ) 147 | indent = ' ' * 4 148 | 149 | refs = scvarsidx.search(q) 150 | if not refs and not q.endswith('*'): 151 | # Try implicit wildcard if not results 152 | refs = scvarsidx.search(q.rstrip() + '*') 153 | docs = [] 154 | for r in refs[:max_results]: 155 | k, name = r['ref'].split('_', 1) 156 | docs.append(dict(scvars[k][name], kind=k)) 157 | 158 | typer.echo( 159 | 'Showing ' 160 | + typer.style(f"{len(docs)}/{len(refs)}", fg=typer.colors.BLUE) 161 | + ' results' 162 | ) 163 | if not docs: 164 | typer.echo(fill(""" 165 | Perhaps try wildcard 'alti*', fuzzy match 'alti~2' 166 | or advanced options at https://lunr.readthedocs.io/en/latest/usage.html 167 | """.strip())) 168 | else: 169 | if len(docs) < len(refs): 170 | typer.echo('Increase --max-results for more') 171 | typer.echo('') 172 | for d in docs: 173 | name = d['name_std'] if ',' in d['name'] else d['name'] 174 | style = styles[d['kind']] 175 | label = typer.style(f"{name}", fg=style['color'], bold=True) 176 | typer.echo(style['symbol'] + ' ' + label + f"{' ✏️' if d.get('settable') else ''}") 177 | if brief: 178 | continue 179 | desc = d.get('description') 180 | if desc: 181 | s = re.sub(r'\s*\n\s*', ' ', desc).strip() 182 | typer.echo(fill(s, initial_indent=indent, subsequent_indent=indent)) 183 | loc = '; '.join(filter(None, [d['page'], d['section'] or None])).lower() 184 | typer.echo(f"{indent}Category: {loc}") 185 | if d.get('units'): 186 | lines = [s for s in d['units'].split('\n') if s.rstrip()] 187 | lines[0] = f"{indent}Default units: {lines[0]} [{d['dimensions']}]" 188 | typer.echo('\n'.join(lines)) 189 | 190 | 191 | if __name__ == "__main__": 192 | app() 193 | -------------------------------------------------------------------------------- /simconnect/datadef.py: -------------------------------------------------------------------------------- 1 | from typing import List, Sequence, Union, Dict, Any, Callable, Optional, Type, TYPE_CHECKING 2 | import logging 3 | import json 4 | from hashlib import sha1 5 | from ctypes import cast, byref, sizeof, POINTER, c_float, c_double, c_longlong, c_char 6 | 7 | from .scvars import validate_simvar, validate_units, validate_event, type_for_unit 8 | from .scdefs import ( 9 | Struct1, RECV_SIMOBJECT_DATA, DATA_REQUEST_FLAG_TAGGED, 10 | DATATYPE_INT32, DATATYPE_INT64, DATATYPE_FLOAT32, DATATYPE_FLOAT64, 11 | DATATYPE_STRING256, DWORD 12 | ) 13 | from .changedict import ChangeDict 14 | if TYPE_CHECKING: 15 | from .sc import SimConnect 16 | 17 | 18 | EPSILON_DEFAULT = 1e-4 19 | 20 | """ 21 | simvars can be specified as: 22 | - a single simvar as a string like "Indicated Altitude" 23 | - a single simvar as a dict of {name: , [units: ], [type: ], [epsilon: ]} 24 | - a list containing a one or more individual simvars 25 | 26 | name: a string matching a SDK variable (case insenstive), 27 | note that simvar names are typically space-separated words, 28 | while event names are underscore-separated. 29 | Indexed variables need a 1-based index, e.g. "ENG MANIFOLD PRESSURE:1" 30 | 31 | units: a string from scvars.json::UNITS as defined in the SDK, 32 | if not present will be inferred using the default from the SDK, 33 | via scvars.json::VARIABLES 34 | 35 | type: one of the supported scdefs.py::DATATYPE_* constants enumerated in _dtyps below. 36 | The default DATATYPE_FLOAT64 (a python float) is good for most simvars. 37 | Strings are supported via DATATYPE_STRING256 (a string of max length 256), 38 | note fixed length is required for datadefs, and enum, boolean, mask and flag simvars 39 | can be represented as DATATYPE_INT32 (a python int) 40 | 41 | epsilon: the precision to detect changes (see SDK), defaulting to 0.0001 42 | """ 43 | SimData = Dict[str, Any] 44 | SimDataHandler = Callable[[SimData], None] 45 | SimVarSpec = Union[str, Dict[str, Any]] 46 | SimVarsSpec = Union[SimVarSpec, Sequence[SimVarSpec]] 47 | 48 | 49 | def _norm_simvars(simvars: SimVarsSpec) -> Sequence[Dict[str, Any]]: 50 | """convert simvars into a seq of dict""" 51 | ds = simvars if isinstance(simvars, (list, tuple)) else [simvars] 52 | return [dict(name=d) if isinstance(d, str) else d for d in ds] 53 | 54 | 55 | class DataDefinition: 56 | _instances: Dict[str, 'DataDefinition'] = {} 57 | 58 | @classmethod 59 | def create(kls, sc: 'SimConnect', simvars: SimVarsSpec, settable=False) -> 'DataDefinition': 60 | """create or retrieve a data definition for the specified variables""" 61 | defs: List[Dict[str, Any]] = [] 62 | svs = _norm_simvars(simvars) 63 | for d in svs: 64 | name = d['name'] 65 | sv = validate_simvar(name, settable) 66 | units = validate_units(name, d.get('units'), sv) 67 | dtyp = d.get('type') or type_for_unit(units) 68 | # see https://forums.flightsimulator.com/t/how-to-read-simvar-of-type-string/502402 69 | if dtyp == DATATYPE_STRING256: units = '' 70 | epsilon = d.get('epsilon', EPSILON_DEFAULT if dtyp == DATATYPE_FLOAT64 else 0) 71 | defs.append(dict(name=name, units=units, dtyp=dtyp, epsilon=epsilon)) 72 | 73 | # if we already have this data definition, re-use it 74 | key = sha1(json.dumps(defs, sort_keys=True).encode('utf-8')).hexdigest() 75 | if key not in kls._instances: 76 | kls._instances[key] = kls(sc, len(kls._instances), defs) 77 | return kls._instances[key] 78 | 79 | def __init__(self, sc: 'SimConnect', def_id: int, defs: List[Dict[str, Any]]): 80 | self.id = def_id 81 | self.simdata: SimData = ChangeDict() 82 | self._struct: Optional[Type[Struct1]] = None 83 | self.defs = defs 84 | for i, d in enumerate(self.defs): 85 | sc.AddToDataDefinition(self.id, d['name'], d['units'], d['dtyp'], d['epsilon'], i) 86 | 87 | def get_units(self) -> Dict[str, str]: 88 | return {d['name']: d['units'] for d in self.defs} 89 | 90 | def add_receiver(self, sc: 'SimConnect', req_id: int, callback: Optional[SimDataHandler] = None): 91 | """Create a receiver for this DataDefinition, given req_id and optional callback""" 92 | def _receiver(recv: RECV_SIMOBJECT_DATA) -> bool: 93 | if recv.dwRequestID != req_id: 94 | return False 95 | 96 | logging.debug(f"DataDefinition[{self.id}]: Reading RECV_SIMOBJECT_DATA for request {req_id}") 97 | # dwData is a placeholder for where the data values start 98 | # so get a void* to that location and cast appropriately 99 | offset = RECV_SIMOBJECT_DATA.dwData.offset 100 | tagged = recv.dwFlags & DATA_REQUEST_FLAG_TAGGED > 0 101 | idx = -1 102 | for _ in range(recv.dwDefineCount): 103 | if tagged: 104 | idx = cast(byref(recv, offset), POINTER(DWORD))[0] 105 | offset += sizeof(DWORD) 106 | else: 107 | idx += 1 108 | d = self.defs[idx] 109 | ctyp = _dtyps[d['dtyp']] 110 | ptr = cast(byref(recv, offset), POINTER(ctyp)) 111 | if ctyp == c_char: # STRING256 112 | val = ptr[:256].rstrip(b'\x00').decode('ascii') 113 | offset += 256 114 | else: 115 | val = ptr[0] 116 | offset += sizeof(ctyp) 117 | self.simdata[d['name']] = val 118 | 119 | if callback: 120 | callback(self.simdata) 121 | return True 122 | 123 | sc.add_receiver(RECV_SIMOBJECT_DATA, _receiver) 124 | 125 | def _pack_data(self, simdata: Dict[str, Any]) -> Struct1: 126 | if self._struct is None: 127 | class kls(Struct1): 128 | _fields_ = [(d['name'], _dtyps[d['dtyp']]) for d in self.defs] 129 | self._struct = kls 130 | 131 | return self._struct(**simdata) 132 | 133 | 134 | def map_event_id(sc: 'SimConnect', event: str) -> int: 135 | s = validate_event(event) 136 | client_id = _event_ids.get(s) 137 | if client_id is None: 138 | client_id = len(_event_ids) 139 | _event_ids[s] = client_id 140 | sc.MapClientEventToSimEvent(client_id, s) 141 | return client_id 142 | 143 | 144 | # Track client-mapped event ids 145 | _event_ids: Dict[str, int] = {} 146 | 147 | 148 | # Map scdefs type flags to ctypes 149 | _dtyps = { 150 | DATATYPE_INT32: DWORD, # 32-bit integer number 151 | DATATYPE_INT64: c_longlong, # 64-bit integer number 152 | DATATYPE_FLOAT32: c_float, # 32-bit floating-point number (float) 153 | DATATYPE_FLOAT64: c_double, # 64-bit floating-point number (double) 154 | DATATYPE_STRING256: c_char, # variable length string 155 | } 156 | -------------------------------------------------------------------------------- /simconnect/receiver.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, Type, Dict 2 | import logging 3 | from ctypes import cast, POINTER 4 | from .scdefs import RECV, RECV_OPEN, RECV_EXCEPTION 5 | from . import scdefs 6 | 7 | 8 | Receiver = Callable[[RECV], bool] 9 | 10 | _exc_map = dict( 11 | (getattr(scdefs, s), s) 12 | for s in dir(scdefs) 13 | if s.startswith('EXCEPTION_') 14 | ) 15 | 16 | def all_subclasses(cls): 17 | return set(cls.__subclasses__()).union( 18 | [s for c in cls.__subclasses__() for s in all_subclasses(c)]) 19 | 20 | 21 | class ReceiverInstance: 22 | # SDK calls trigger responses which are subclasses of RECV 23 | # indicated by a corresponding RECV_ID_* constant 24 | # for example a response with recv.dwID = RECV_ID_OPEN 25 | # indicates the full response is a RECV_OPEN structure 26 | _recv_map: Dict[str, type] = { 27 | getattr(scdefs, kls.__name__.replace('RECV_', 'RECV_ID_'), None): kls 28 | for kls in all_subclasses(RECV) 29 | } 30 | 31 | def __init__(self, rtype: Type[RECV], receiver: Receiver): 32 | self._rtype = rtype 33 | self._receiver = receiver 34 | 35 | @staticmethod 36 | def cast_recv(pRecv) -> RECV: #TODO type annotation : pointer[RECV] per https://github.com/python/mypy/issues/7540 37 | recv_id = pRecv.contents.dwID 38 | if recv_id in ReceiverInstance._recv_map: 39 | pRecv = cast(pRecv, POINTER(ReceiverInstance._recv_map[recv_id])) 40 | return pRecv.contents 41 | 42 | def receive(self, recv: RECV) -> bool: 43 | if isinstance(recv, self._rtype): 44 | return self._receiver(recv) 45 | else: 46 | return False 47 | 48 | 49 | def receiveException(recv: RECV_EXCEPTION) -> bool: 50 | excid = recv.dwException 51 | excname = _exc_map.get(excid, '') 52 | logging.warning( 53 | f"sc.receiveNext: exception {excname}({excid}), sendID {recv.dwSendID}, index {recv.dwIndex}" 54 | ) 55 | return True 56 | 57 | 58 | def receiveOpen(recv: RECV_OPEN) -> bool: 59 | appVer = f"v{recv.dwApplicationVersionMajor}.{recv.dwApplicationVersionMinor}" 60 | appBuild = f"build {recv.dwApplicationBuildMajor}.{recv.dwApplicationBuildMinor}" 61 | scVer = f"v{recv.dwSimConnectVersionMajor}.{recv.dwSimConnectVersionMinor}" 62 | scBuild = f"build {recv.dwSimConnectBuildMajor}.{recv.dwSimConnectBuildMinor}" 63 | logging.info( 64 | f"Open: App {recv.szApplicationName} {appVer} {appBuild} SimConnect: {scVer} {scBuild}" 65 | ) 66 | return True 67 | 68 | 69 | _default_receivers = [ 70 | ReceiverInstance(RECV_EXCEPTION, receiveException), 71 | ReceiverInstance(RECV_OPEN, receiveOpen), 72 | ] 73 | -------------------------------------------------------------------------------- /simconnect/sc.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional, Type, Any 2 | from ctypes import byref, sizeof, cast, POINTER, c_void_p 3 | import itertools 4 | import logging 5 | import os 6 | from time import time, sleep 7 | from .scdefs import ( 8 | _decls, DispatchProc, 9 | RECV, DATA_REQUEST_FLAG_CHANGED, DATA_REQUEST_FLAG_TAGGED, 10 | OBJECT_ID_USER, PERIOD_SECOND, PERIOD_ONCE, 11 | GROUP_PRIORITY_HIGHEST, EVENT_FLAG_GROUPID_IS_PRIORITY, 12 | HANDLE, windll, 13 | ) 14 | from .receiver import Receiver, ReceiverInstance, _default_receivers 15 | from .datadef import SimVarsSpec, DataDefinition, SimData, SimDataHandler, _norm_simvars, map_event_id 16 | 17 | 18 | RECV_P = POINTER(RECV) 19 | 20 | # to change the default logging, set the LOGLEVEL environment variable, e.g. LOGLEVEL=DEBUG 21 | logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) 22 | 23 | _dll_path = os.path.join(os.path.dirname(__file__), 'SimConnect.dll') 24 | 25 | 26 | class SimConnect: 27 | def __init__( 28 | self, 29 | name='pySimConnect', 30 | dll_path=_dll_path, 31 | default_receivers=_default_receivers, 32 | poll_interval_seconds=0.05): 33 | try: 34 | dll = windll.LoadLibrary(dll_path) 35 | except Exception: 36 | logging.error(f"Failed to load SimConnect DLL from {dll_path}") 37 | raise 38 | self._decls = _decls(dll) 39 | self.hsc = HANDLE() 40 | # All methods other than open pass the sc HANDLE as the first arg 41 | try: 42 | self._decls['Open'](byref(self.hsc), name.encode('utf-8'), None, 0, 0, 0) 43 | except OSError: 44 | logging.error("Failed to open SimConnect, is Flight Simulator running?") 45 | raise 46 | self._reqid_iter = itertools.count() 47 | self._receivers: List[ReceiverInstance] = default_receivers[:] 48 | self.poll_interval_seconds = poll_interval_seconds 49 | 50 | def __enter__(self): 51 | return self 52 | 53 | def __exit__(self, type, value, traceback): 54 | self.Close() 55 | 56 | def __getattr__(self, k): 57 | if k in self._decls: 58 | return self._dispatch(self._decls[k]) 59 | # Default behaviour 60 | raise AttributeError 61 | 62 | def _dispatch(self, f): 63 | """Dispatch to a registered method, using our open handle""" 64 | def _callable(*args): 65 | args = [arg.encode('utf-8') if isinstance(arg, str) else arg for arg in args] 66 | return f(self.hsc, *args) 67 | return _callable 68 | 69 | def add_receiver(self, rtype: Type[RECV], receiver: Receiver): 70 | """ 71 | Adds a receiver to handle type recv_type 72 | Any additional kwargs will be passed to the receiver when it's called 73 | Returns an identifer for the receiver which can be used to remove it 74 | """ 75 | self._receivers.append(ReceiverInstance(rtype, receiver)) 76 | 77 | def remove_receiver(self, receiver: Receiver) -> bool: 78 | """Remove a receiver instance by id, return True if found""" 79 | n = len(self._receivers) 80 | self._receivers = [r for r in self._receivers if r._receiver == receiver] 81 | return len(self._receivers) < n 82 | 83 | def _dispatcher(self, pRecv, nSize, pContext): 84 | """Dispatch to all our handlers whenever we get a RECV object""" 85 | recv = ReceiverInstance.cast_recv(pRecv) 86 | logging.debug(f"receive: got {recv.__class__.__name__} with size {nSize} and context {pContext}") 87 | self._received = sum(r.receive(recv) for r in self._receivers) 88 | if not self._received: 89 | logging.warn(f"receive: no receiver found for {recv.__class__.__name__}") 90 | 91 | def receive(self, timeout_seconds=None) -> bool: 92 | """ 93 | Poll the SDK for messages, dispatching to registered receivers. 94 | Poll at least once, until either we receive a message or timeout expires 95 | Returns true if we received a message 96 | """ 97 | tmax = time() + timeout_seconds if timeout_seconds else None 98 | self._received = 0 99 | while True: 100 | self.CallDispatch(DispatchProc(self._dispatcher), None) 101 | if self._received or not tmax or time() > tmax: 102 | break 103 | sleep(self.poll_interval_seconds) 104 | return self._received > 0 105 | 106 | def get_simdatum( 107 | self, 108 | name, 109 | units=None, 110 | timeout_seconds=1) -> Any: 111 | """get a one-off value of a single simvar variable, see also subscribe_simdata""" 112 | spec = dict(name=name, units=units) 113 | simdata = self.get_simdata([spec], timeout_seconds) 114 | return list(simdata.values())[0] if simdata else None 115 | 116 | def get_simdata( 117 | self, 118 | simvars: SimVarsSpec, 119 | timeout_seconds=1) -> SimData: 120 | """ 121 | get a snapshot of one or more simvars. 122 | if you plan to query the same data frequently use subscribe_simdata instead. 123 | waits up to timeout_seconds for a response, 124 | returning SimData (a dictionary that supports changedsince, see changedict.py) 125 | """ 126 | dd = self.subscribe_simdata(simvars, period=PERIOD_ONCE, repeat_count=1, flags=0) 127 | tmax = time() + (timeout_seconds or 1) 128 | # we'll potentially receive other messages while we're looking for this result 129 | # so wait up to timeout_seconds total while there are messages and we haven't got data yet 130 | while self.receive(tmax - time()) and not dd.simdata: 131 | pass 132 | self._receivers.pop() 133 | return dd.simdata 134 | 135 | def subscribe_simdata( 136 | self, simvars: SimVarsSpec, 137 | period=PERIOD_SECOND, 138 | skip_periods=0, # number of periods to skip before starting 139 | interval=1, # number of periods between updates 140 | repeat_count=0, # number of updates before stopping (0 = forever) 141 | flags=DATA_REQUEST_FLAG_CHANGED | DATA_REQUEST_FLAG_TAGGED, 142 | callback: Optional[SimDataHandler] = None 143 | ): 144 | """ 145 | Create and subscribe to a data definition. 146 | The returned data definition provides methods to access the 147 | current data (via dd.simdata) and inferred units etc. 148 | If the optional callback is provided, it will be called 149 | with dd.simdata whenever the data is changed. 150 | """ 151 | dd = DataDefinition.create(self, simvars) 152 | req_id = next(self._reqid_iter) 153 | dd.add_receiver(self, req_id, callback) 154 | # note the SDK doc for first two args is misleading/wrong 155 | self.RequestDataOnSimObject( 156 | req_id, 157 | dd.id, 158 | OBJECT_ID_USER, 159 | period, 160 | flags, 161 | skip_periods, 162 | interval, 163 | repeat_count 164 | ) 165 | return dd 166 | 167 | def set_simdatum(self, name, value, units=None): 168 | """Set a single simulator variable""" 169 | self.set_simdata([dict(name=name, units=units, value=value)]) 170 | 171 | def set_simdata(self, simdata: SimVarsSpec): 172 | """ 173 | Set one or more simulator variables, based on a list 174 | of dictionary of {name: , value: , [units: ], [type: ]} 175 | """ 176 | sds = _norm_simvars(simdata) 177 | dd = DataDefinition.create(self, sds, settable=True) 178 | assert all(['value' in d for d in sds]), "set_simdata: must specify value for each item" 179 | values = {d['name']: d['value'] for d in sds} 180 | data = dd._pack_data(values) 181 | logging.debug(f"setting simdata {sds} with {sizeof(data)} bytes") 182 | #TODO: some data types can be also be set as array, 183 | # e.g. any number of waypoints can be given to an AI object using a single call to this function, 184 | # and any number of marker state structures can also be combined into an array 185 | # in that case number of items would be greater than 1 186 | self.SetDataOnSimObject( 187 | dd.id, 188 | OBJECT_ID_USER, 189 | 0, # flags 190 | 0, # number of items, 0 is also interpreted as 1... 191 | sizeof(data), # DWORD size of each item 192 | cast(byref(data), c_void_p), # pointer to start of data 193 | ) 194 | 195 | def send_event(self, event, data=0): 196 | """Send an event to FlightSim, see datadef.EVENTS""" 197 | client_id = map_event_id(self, event) 198 | self.TransmitClientEvent( 199 | OBJECT_ID_USER, 200 | client_id, 201 | data, 202 | GROUP_PRIORITY_HIGHEST, 203 | EVENT_FLAG_GROUPID_IS_PRIORITY, 204 | ) 205 | -------------------------------------------------------------------------------- /simconnect/scdefs.py: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT: Auto generated by genscdefs.py 3 | # 4 | from ctypes import ( 5 | c_bool, c_char, c_int, c_long, c_float, c_double, 6 | c_char_p, c_void_p, 7 | Structure, POINTER, 8 | ) 9 | try: 10 | from ctypes import HRESULT, WINFUNCTYPE, windll 11 | from ctypes.wintypes import BYTE, WORD, DWORD, HANDLE, LPCSTR, HWND 12 | except: 13 | from .winstubs import HRESULT, WINFUNCTYPE, windll 14 | from .winstubs import BYTE, WORD, DWORD, HANDLE, LPCSTR, HWND 15 | 16 | 17 | c_float_p = POINTER(c_float) 18 | FLT_MAX = 3.402823466e+38 19 | MAX_PATH = 260 20 | 21 | 22 | class GUID(Structure): 23 | _fields_ = [ 24 | ("Data1", DWORD), 25 | ("Data2", WORD), 26 | ("Data3", WORD), 27 | ("Data4", BYTE * 8) 28 | ] 29 | 30 | 31 | class Struct1(Structure): 32 | _pack_ = 1 # implement the pragma(push, 1) 33 | 34 | 35 | # 0 "SimConnect.h" 36 | # 0 "" 37 | # 0 "" 38 | # 1 "SimConnect.h" 39 | # ----------------------------------------------------------------------------- 40 | # 41 | # Copyright (c) Microsoft Corporation. All Rights Reserved. 42 | # 43 | # ----------------------------------------------------------------------------- 44 | 45 | 46 | 47 | 48 | 49 | # 22 "SimConnect.h" 50 | # 1 "./float.h" 1 51 | # 23 "SimConnect.h" 2 52 | 53 | OBJECT_ID = DWORD 54 | 55 | # ---------------------------------------------------------------------------- 56 | # Constants 57 | # ---------------------------------------------------------------------------- 58 | 59 | UNUSED = 0xFFFFFFFF # special value to indicate unused event, ID 60 | OBJECT_ID_USER = 0 # proxy value for User vehicle ObjectID 61 | 62 | CAMERA_IGNORE_FIELD = FLT_MAX # Used to tell the Camera API to NOT modify the value in this part of the argument. 63 | 64 | CLIENTDATA_MAX_SIZE = 8192 # maximum value for SimConnect_CreateClientData dwSize parameter 65 | 66 | 67 | # Notification Group priority values 68 | GROUP_PRIORITY_HIGHEST = 1 # highest priority 69 | GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000 # highest priority that allows events to be masked 70 | GROUP_PRIORITY_STANDARD = 1900000000 # standard priority 71 | GROUP_PRIORITY_DEFAULT = 2000000000 # default priority 72 | GROUP_PRIORITY_LOWEST = 4000000000 # priorities lower than this will be ignored 73 | 74 | # Weather observations Metar strings 75 | MAX_METAR_LENGTH = 2000 76 | 77 | # Maximum thermal size is 100 km. 78 | MAX_THERMAL_SIZE = 100000 79 | MAX_THERMAL_RATE = 1000 80 | 81 | # SIMCONNECT_DATA_INITPOSITION.Airspeed 82 | INITPOSITION_AIRSPEED_CRUISE = -1 # aircraft's cruise airspeed 83 | INITPOSITION_AIRSPEED_KEEP = -2 # keep current airspeed 84 | 85 | # AddToClientDataDefinition dwSizeOrType parameter type values 86 | CLIENTDATATYPE_INT8 = -1 # 8-bit integer number 87 | CLIENTDATATYPE_INT16 = -2 # 16-bit integer number 88 | CLIENTDATATYPE_INT32 = -3 # 32-bit integer number 89 | CLIENTDATATYPE_INT64 = -4 # 64-bit integer number 90 | CLIENTDATATYPE_FLOAT32 = -5 # 32-bit floating-point number (float) 91 | CLIENTDATATYPE_FLOAT64 = -6 # 64-bit floating-point number (double) 92 | 93 | # AddToClientDataDefinition dwOffset parameter special values 94 | CLIENTDATAOFFSET_AUTO = -1 # automatically compute offset of the ClientData variable 95 | 96 | # Open ConfigIndex parameter special value 97 | OPEN_CONFIGINDEX_LOCAL = -1 # ignore SimConnect.cfg settings, and force local connection 98 | 99 | # ---------------------------------------------------------------------------- 100 | # Enum definitions 101 | # ---------------------------------------------------------------------------- 102 | 103 | # these came from substituteMacros 104 | # 88 "SimConnect.h" 105 | # Receive data types 106 | RECV_ID = DWORD 107 | RECV_ID_NULL = 0x00 108 | RECV_ID_EXCEPTION = 0x01 109 | RECV_ID_OPEN = 0x02 110 | RECV_ID_QUIT = 0x03 111 | RECV_ID_EVENT = 0x04 112 | RECV_ID_EVENT_OBJECT_ADDREMOVE = 0x05 113 | RECV_ID_EVENT_FILENAME = 0x06 114 | RECV_ID_EVENT_FRAME = 0x07 115 | RECV_ID_SIMOBJECT_DATA = 0x08 116 | RECV_ID_SIMOBJECT_DATA_BYTYPE = 0x09 117 | RECV_ID_WEATHER_OBSERVATION = 0x0A 118 | RECV_ID_CLOUD_STATE = 0x0B 119 | RECV_ID_ASSIGNED_OBJECT_ID = 0x0C 120 | RECV_ID_RESERVED_KEY = 0x0D 121 | RECV_ID_CUSTOM_ACTION = 0x0E 122 | RECV_ID_SYSTEM_STATE = 0x0F 123 | RECV_ID_CLIENT_DATA = 0x10 124 | RECV_ID_EVENT_WEATHER_MODE = 0x11 125 | RECV_ID_AIRPORT_LIST = 0x12 126 | RECV_ID_VOR_LIST = 0x13 127 | RECV_ID_NDB_LIST = 0x14 128 | RECV_ID_WAYPOINT_LIST = 0x15 129 | RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED = 0x16 130 | RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED = 0x17 131 | RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED = 0x18 132 | RECV_ID_EVENT_RACE_END = 0x19 133 | RECV_ID_EVENT_RACE_LAP = 0x1A 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | # Data data types 142 | DATATYPE = DWORD 143 | DATATYPE_INVALID = 0x00 # invalid data type 144 | DATATYPE_INT32 = 0x01 # 32-bit integer number 145 | DATATYPE_INT64 = 0x02 # 64-bit integer number 146 | DATATYPE_FLOAT32 = 0x03 # 32-bit floating-point number (float) 147 | DATATYPE_FLOAT64 = 0x04 # 64-bit floating-point number (double) 148 | DATATYPE_STRING8 = 0x05 # 8-byte string 149 | DATATYPE_STRING32 = 0x06 # 32-byte string 150 | DATATYPE_STRING64 = 0x07 # 64-byte string 151 | DATATYPE_STRING128 = 0x08 # 128-byte string 152 | DATATYPE_STRING256 = 0x09 # 256-byte string 153 | DATATYPE_STRING260 = 0x0A # 260-byte string 154 | DATATYPE_STRINGV = 0x0B # variable-length string 155 | 156 | DATATYPE_INITPOSITION = 0x0C # see SIMCONNECT_DATA_INITPOSITION 157 | DATATYPE_MARKERSTATE = 0x0D # see SIMCONNECT_DATA_MARKERSTATE 158 | DATATYPE_WAYPOINT = 0x0E # see SIMCONNECT_DATA_WAYPOINT 159 | DATATYPE_LATLONALT = 0x0F # see SIMCONNECT_DATA_LATLONALT 160 | DATATYPE_XYZ = 0x10 # see SIMCONNECT_DATA_XYZ 161 | 162 | DATATYPE_MAX = 0x11 # enum limit 163 | 164 | 165 | # Exception error types 166 | EXCEPTION = DWORD 167 | EXCEPTION_NONE = 0x00 168 | 169 | EXCEPTION_ERROR = 0x01 170 | EXCEPTION_SIZE_MISMATCH = 0x02 171 | EXCEPTION_UNRECOGNIZED_ID = 0x03 172 | EXCEPTION_UNOPENED = 0x04 173 | EXCEPTION_VERSION_MISMATCH = 0x05 174 | EXCEPTION_TOO_MANY_GROUPS = 0x06 175 | EXCEPTION_NAME_UNRECOGNIZED = 0x07 176 | EXCEPTION_TOO_MANY_EVENT_NAMES = 0x08 177 | EXCEPTION_EVENT_ID_DUPLICATE = 0x09 178 | EXCEPTION_TOO_MANY_MAPS = 0x0A 179 | EXCEPTION_TOO_MANY_OBJECTS = 0x0B 180 | EXCEPTION_TOO_MANY_REQUESTS = 0x0C 181 | EXCEPTION_WEATHER_INVALID_PORT = 0x0D 182 | EXCEPTION_WEATHER_INVALID_METAR = 0x0E 183 | EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION = 0x0F 184 | EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION = 0x10 185 | EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION = 0x11 186 | EXCEPTION_INVALID_DATA_TYPE = 0x12 187 | EXCEPTION_INVALID_DATA_SIZE = 0x13 188 | EXCEPTION_DATA_ERROR = 0x14 189 | EXCEPTION_INVALID_ARRAY = 0x15 190 | EXCEPTION_CREATE_OBJECT_FAILED = 0x16 191 | EXCEPTION_LOAD_FLIGHTPLAN_FAILED = 0x17 192 | EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE = 0x18 193 | EXCEPTION_ILLEGAL_OPERATION = 0x19 194 | EXCEPTION_ALREADY_SUBSCRIBED = 0x1A 195 | EXCEPTION_INVALID_ENUM = 0x1B 196 | EXCEPTION_DEFINITION_ERROR = 0x1C 197 | EXCEPTION_DUPLICATE_ID = 0x1D 198 | EXCEPTION_DATUM_ID = 0x1E 199 | EXCEPTION_OUT_OF_BOUNDS = 0x1F 200 | EXCEPTION_ALREADY_CREATED = 0x20 201 | EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE = 0x21 202 | EXCEPTION_OBJECT_CONTAINER = 0x22 203 | EXCEPTION_OBJECT_AI = 0x23 204 | EXCEPTION_OBJECT_ATC = 0x24 205 | EXCEPTION_OBJECT_SCHEDULE = 0x25 206 | 207 | 208 | # Object types 209 | SIMOBJECT_TYPE = DWORD 210 | SIMOBJECT_TYPE_USER = 0x00 211 | SIMOBJECT_TYPE_ALL = 0x01 212 | SIMOBJECT_TYPE_AIRCRAFT = 0x02 213 | SIMOBJECT_TYPE_HELICOPTER = 0x03 214 | SIMOBJECT_TYPE_BOAT = 0x04 215 | SIMOBJECT_TYPE_GROUND = 0x05 216 | 217 | 218 | # EventState values 219 | STATE = DWORD 220 | STATE_OFF = 0x00 221 | STATE_ON = 0x01 222 | 223 | 224 | # Object Data Request Period values 225 | PERIOD = DWORD 226 | PERIOD_NEVER = 0x00 227 | PERIOD_ONCE = 0x01 228 | PERIOD_VISUAL_FRAME = 0x02 229 | PERIOD_SIM_FRAME = 0x03 230 | PERIOD_SECOND = 0x04 231 | 232 | 233 | 234 | MISSION_END = DWORD 235 | MISSION_FAILED = 0x00 236 | MISSION_CRASHED = 0x01 237 | MISSION_SUCCEEDED = 0x02 238 | 239 | 240 | # ClientData Request Period values 241 | CLIENT_DATA_PERIOD = DWORD 242 | CLIENT_DATA_PERIOD_NEVER = 0x00 243 | CLIENT_DATA_PERIOD_ONCE = 0x01 244 | CLIENT_DATA_PERIOD_VISUAL_FRAME = 0x02 245 | CLIENT_DATA_PERIOD_ON_SET = 0x03 246 | CLIENT_DATA_PERIOD_SECOND = 0x04 247 | 248 | 249 | TEXT_TYPE = DWORD 250 | TEXT_TYPE_SCROLL_BLACK = 0x00 251 | TEXT_TYPE_SCROLL_WHITE = 0x01 252 | TEXT_TYPE_SCROLL_RED = 0x02 253 | TEXT_TYPE_SCROLL_GREEN = 0x03 254 | TEXT_TYPE_SCROLL_BLUE = 0x04 255 | TEXT_TYPE_SCROLL_YELLOW = 0x05 256 | TEXT_TYPE_SCROLL_MAGENTA = 0x06 257 | TEXT_TYPE_SCROLL_CYAN = 0x07 258 | TEXT_TYPE_PRINT_BLACK = 0x100 259 | TEXT_TYPE_PRINT_WHITE = 0x101 260 | TEXT_TYPE_PRINT_RED = 0x102 261 | TEXT_TYPE_PRINT_GREEN = 0x103 262 | TEXT_TYPE_PRINT_BLUE = 0x104 263 | TEXT_TYPE_PRINT_YELLOW = 0x105 264 | TEXT_TYPE_PRINT_MAGENTA = 0x106 265 | TEXT_TYPE_PRINT_CYAN = 0x107 266 | TEXT_TYPE_MENU = 0x200 267 | 268 | 269 | TEXT_RESULT = DWORD 270 | TEXT_RESULT_MENU_SELECT_1 = 0x00 271 | TEXT_RESULT_MENU_SELECT_2 = 0x01 272 | TEXT_RESULT_MENU_SELECT_3 = 0x02 273 | TEXT_RESULT_MENU_SELECT_4 = 0x03 274 | TEXT_RESULT_MENU_SELECT_5 = 0x04 275 | TEXT_RESULT_MENU_SELECT_6 = 0x05 276 | TEXT_RESULT_MENU_SELECT_7 = 0x06 277 | TEXT_RESULT_MENU_SELECT_8 = 0x07 278 | TEXT_RESULT_MENU_SELECT_9 = 0x08 279 | TEXT_RESULT_MENU_SELECT_10 = 0x09 280 | TEXT_RESULT_DISPLAYED = 0x10000 281 | TEXT_RESULT_QUEUED = 0x10001 282 | TEXT_RESULT_REMOVED = 0x10002 283 | TEXT_RESULT_REPLACED = 0x10003 284 | TEXT_RESULT_TIMEOUT = 0x10004 285 | 286 | 287 | WEATHER_MODE = DWORD 288 | WEATHER_MODE_THEME = 0x00 289 | WEATHER_MODE_RWW = 0x01 290 | WEATHER_MODE_CUSTOM = 0x02 291 | WEATHER_MODE_GLOBAL = 0x03 292 | 293 | 294 | FACILITY_LIST_TYPE = DWORD 295 | FACILITY_LIST_TYPE_AIRPORT = 0x00 296 | FACILITY_LIST_TYPE_WAYPOINT = 0x01 297 | FACILITY_LIST_TYPE_NDB = 0x02 298 | FACILITY_LIST_TYPE_VOR = 0x03 299 | FACILITY_LIST_TYPE_COUNT = 0x04 # invalid 300 | 301 | 302 | 303 | VOR_FLAGS = DWORD # flags for SIMCONNECT_RECV_ID_VOR_LIST 304 | RECV_ID_VOR_LIST_HAS_NAV_SIGNAL = 0x00000001 # Has Nav signal 305 | RECV_ID_VOR_LIST_HAS_LOCALIZER = 0x00000002 # Has localizer 306 | RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE = 0x00000004 # Has Nav signal 307 | RECV_ID_VOR_LIST_HAS_DME = 0x00000008 # Station has DME 308 | 309 | 310 | 311 | # bits for the Waypoint Flags field: may be combined 312 | WAYPOINT_FLAGS = DWORD 313 | WAYPOINT_NONE = 0x00 314 | WAYPOINT_SPEED_REQUESTED = 0x04 # requested speed at waypoint is valid 315 | WAYPOINT_THROTTLE_REQUESTED = 0x08 # request a specific throttle percentage 316 | WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10 # compute vertical to speed to reach waypoint altitude when crossing the waypoint 317 | WAYPOINT_ALTITUDE_IS_AGL = 0x20 # AltitudeIsAGL 318 | WAYPOINT_ON_GROUND = 0x00100000 # place this waypoint on the ground 319 | WAYPOINT_REVERSE = 0x00200000 # Back up to this waypoint. Only valid on first waypoint 320 | WAYPOINT_WRAP_TO_FIRST = 0x00400000 # Wrap around back to first waypoint. Only valid on last waypoint. 321 | 322 | EVENT_FLAG = DWORD 323 | EVENT_FLAG_DEFAULT = 0x00000000 324 | EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001 # set event repeat timer to simulate fast repeat 325 | EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002 # set event repeat timer to simulate slow repeat 326 | EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010 # interpret GroupID parameter as priority value 327 | 328 | DATA_REQUEST_FLAG = DWORD 329 | DATA_REQUEST_FLAG_DEFAULT = 0x00000000 330 | DATA_REQUEST_FLAG_CHANGED = 0x00000001 # send requested data when value(s) change 331 | DATA_REQUEST_FLAG_TAGGED = 0x00000002 # send requested data in tagged format 332 | 333 | DATA_SET_FLAG = DWORD 334 | DATA_SET_FLAG_DEFAULT = 0x00000000 335 | DATA_SET_FLAG_TAGGED = 0x00000001 # data is in tagged format 336 | 337 | CREATE_CLIENT_DATA_FLAG = DWORD 338 | CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000 339 | CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001 # permit only ClientData creator to write into ClientData 340 | 341 | 342 | CLIENT_DATA_REQUEST_FLAG = DWORD 343 | CLIENT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000 344 | CLIENT_DATA_REQUEST_FLAG_CHANGED = 0x00000001 # send requested ClientData when value(s) change 345 | CLIENT_DATA_REQUEST_FLAG_TAGGED = 0x00000002 # send requested ClientData in tagged format 346 | 347 | CLIENT_DATA_SET_FLAG = DWORD 348 | CLIENT_DATA_SET_FLAG_DEFAULT = 0x00000000 349 | CLIENT_DATA_SET_FLAG_TAGGED = 0x00000001 # data is in tagged format 350 | 351 | 352 | VIEW_SYSTEM_EVENT_DATA = DWORD # dwData contains these flags for the "View" System Event 353 | VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001 # 2D Panels in cockpit view 354 | VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002 # Virtual (3D) panels in cockpit view 355 | VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004 # Orthogonal (Map) view 356 | 357 | SOUND_SYSTEM_EVENT_DATA = DWORD # dwData contains these flags for the "Sound" System Event 358 | SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001 # Sound Master 359 | # 357 "SimConnect.h" 360 | # ---------------------------------------------------------------------------- 361 | # User-defined enums 362 | # ---------------------------------------------------------------------------- 363 | 364 | NOTIFICATION_GROUP_ID = DWORD # client-defined notification group ID 365 | INPUT_GROUP_ID = DWORD # client-defined input group ID 366 | DATA_DEFINITION_ID = DWORD # client-defined data definition ID 367 | DATA_REQUEST_ID = DWORD # client-defined request data ID 368 | 369 | CLIENT_EVENT_ID = DWORD # client-defined client event ID 370 | CLIENT_DATA_ID = DWORD # client-defined client data ID 371 | CLIENT_DATA_DEFINITION_ID = DWORD # client-defined client data definition ID 372 | 373 | 374 | # ---------------------------------------------------------------------------- 375 | # Struct definitions 376 | # ---------------------------------------------------------------------------- 377 | 378 | #pragma pack(push, 1) 379 | 380 | class RECV(Struct1): 381 | _fields_ = [ 382 | ("dwSize", DWORD), # record size 383 | ("dwVersion", DWORD), # interface version 384 | ("dwID", DWORD), # see SIMCONNECT_RECV_ID 385 | ] 386 | 387 | 388 | class RECV_EXCEPTION(RECV): 389 | UNKNOWN_SENDID = 0 390 | UNKNOWN_INDEX = 0xFFFFFFFF 391 | _fields_ = [ 392 | ("dwException", DWORD), # see SIMCONNECT_EXCEPTION 393 | ("dwSendID", DWORD), # see SimConnect_GetLastSentPacketID 394 | ("dwIndex", DWORD), # index of parameter that was source of error 395 | ] 396 | 397 | 398 | class RECV_OPEN(RECV): 399 | _fields_ = [ 400 | ("szApplicationName", c_char * 256), 401 | ("dwApplicationVersionMajor", DWORD), 402 | ("dwApplicationVersionMinor", DWORD), 403 | ("dwApplicationBuildMajor", DWORD), 404 | ("dwApplicationBuildMinor", DWORD), 405 | ("dwSimConnectVersionMajor", DWORD), 406 | ("dwSimConnectVersionMinor", DWORD), 407 | ("dwSimConnectBuildMajor", DWORD), 408 | ("dwSimConnectBuildMinor", DWORD), 409 | ("dwReserved1", DWORD), 410 | ("dwReserved2", DWORD), 411 | ] 412 | 413 | 414 | class RECV_QUIT(RECV): 415 | _fields_ = [ 416 | ] 417 | 418 | 419 | class RECV_EVENT(RECV): 420 | UNKNOWN_GROUP = 0xFFFFFFFF 421 | _fields_ = [ 422 | ("uGroupID", DWORD), 423 | ("uEventID", DWORD), 424 | ("dwData", DWORD), # uEventID-dependent context 425 | ] 426 | 427 | 428 | class RECV_EVENT_FILENAME(RECV_EVENT): 429 | _fields_ = [ 430 | ("szFileName", c_char * MAX_PATH), # uEventID-dependent context 431 | ("dwFlags", DWORD), 432 | ] 433 | 434 | 435 | class RECV_EVENT_OBJECT_ADDREMOVE(RECV_EVENT): 436 | _fields_ = [ 437 | ("eObjType", SIMOBJECT_TYPE), 438 | ] 439 | 440 | 441 | class RECV_EVENT_FRAME(RECV_EVENT): 442 | _fields_ = [ 443 | ("fFrameRate", c_float), 444 | ("fSimSpeed", c_float), 445 | ] 446 | 447 | 448 | class RECV_EVENT_MULTIPLAYER_SERVER_STARTED(RECV_EVENT): 449 | # No event specific data, for now 450 | _fields_ = [ 451 | ] 452 | 453 | 454 | class RECV_EVENT_MULTIPLAYER_CLIENT_STARTED(RECV_EVENT): 455 | # No event specific data, for now 456 | _fields_ = [ 457 | ] 458 | 459 | 460 | class RECV_EVENT_MULTIPLAYER_SESSION_ENDED(RECV_EVENT): 461 | # No event specific data, for now 462 | _fields_ = [ 463 | ] 464 | 465 | 466 | # SIMCONNECT_DATA_RACE_RESULT 467 | class DATA_RACE_RESULT(Struct1): 468 | _fields_ = [ 469 | ("dwNumberOfRacers", DWORD), # The total number of racers 470 | ("MissionGUID", GUID), # The name of the mission to execute, NULL if no mission 471 | ("szPlayerName", c_char * MAX_PATH), # The name of the player 472 | ("szSessionType", c_char * MAX_PATH), # The type of the multiplayer session: "LAN", "GAMESPY") 473 | ("szAircraft", c_char * MAX_PATH), # The aircraft type 474 | ("szPlayerRole", c_char * MAX_PATH), # The player role in the mission 475 | ("fTotalTime", c_double), # Total time in seconds, 0 means DNF 476 | ("fPenaltyTime", c_double), # Total penalty time in seconds 477 | ("dwIsDisqualified", DWORD), # non 0 - disqualified, 0 - not disqualified 478 | ] 479 | 480 | 481 | class RECV_EVENT_RACE_END(RECV_EVENT): 482 | _fields_ = [ 483 | ("dwRacerNumber", DWORD), # The index of the racer the results are for 484 | ("RacerData", DATA_RACE_RESULT), 485 | ] 486 | 487 | 488 | class RECV_EVENT_RACE_LAP(RECV_EVENT): 489 | _fields_ = [ 490 | ("dwLapIndex", DWORD), # The index of the lap the results are for 491 | ("RacerData", DATA_RACE_RESULT), 492 | ] 493 | 494 | 495 | class RECV_SIMOBJECT_DATA(RECV): 496 | _fields_ = [ 497 | ("dwRequestID", DWORD), 498 | ("dwObjectID", DWORD), 499 | ("dwDefineID", DWORD), 500 | ("dwFlags", DWORD), # SIMCONNECT_DATA_REQUEST_FLAG 501 | ("dwentrynumber", DWORD), # if multiple objects returned, this is number out of . 502 | ("dwoutof", DWORD), # note: starts with 1, not 0. 503 | ("dwDefineCount", DWORD), # data count (number of datums, *not* byte count) 504 | ("dwData", DWORD), # data begins here, dwDefineCount data items 505 | ] 506 | 507 | 508 | class RECV_SIMOBJECT_DATA_BYTYPE(RECV_SIMOBJECT_DATA): 509 | _fields_ = [ 510 | ] 511 | 512 | 513 | class RECV_CLIENT_DATA(RECV_SIMOBJECT_DATA): 514 | _fields_ = [ 515 | ] 516 | 517 | 518 | class RECV_WEATHER_OBSERVATION(RECV): 519 | _fields_ = [ 520 | ("dwRequestID", DWORD), 521 | ("szMetar", c_char * 1), # Variable length string whose maximum size is MAX_METAR_LENGTH 522 | ] 523 | 524 | 525 | CLOUD_STATE_ARRAY_WIDTH = int(64) 526 | CLOUD_STATE_ARRAY_SIZE = int(CLOUD_STATE_ARRAY_WIDTH*CLOUD_STATE_ARRAY_WIDTH) 527 | 528 | class RECV_CLOUD_STATE(RECV): 529 | _fields_ = [ 530 | ("dwRequestID", DWORD), 531 | ("dwArraySize", DWORD), 532 | ("rgbData", BYTE * 1), 533 | ] 534 | 535 | 536 | class RECV_ASSIGNED_OBJECT_ID(RECV): 537 | _fields_ = [ 538 | ("dwRequestID", DWORD), 539 | ("dwObjectID", DWORD), 540 | ] 541 | 542 | 543 | class RECV_RESERVED_KEY(RECV): 544 | _fields_ = [ 545 | ("szChoiceReserved", c_char * 30), 546 | ("szReservedKey", c_char * 50), 547 | ] 548 | 549 | 550 | class RECV_SYSTEM_STATE(RECV): 551 | _fields_ = [ 552 | ("dwRequestID", DWORD), 553 | ("dwInteger", DWORD), 554 | ("fFloat", c_float), 555 | ("szString", c_char * MAX_PATH), 556 | ] 557 | 558 | 559 | class RECV_CUSTOM_ACTION(RECV_EVENT): 560 | _fields_ = [ 561 | ("guidInstanceId", GUID), # Instance id of the action that executed 562 | ("dwWaitForCompletion", DWORD), # Wait for completion flag on the action 563 | ("szPayLoad", c_char * 1), # Variable length string payload associated with the mission action. 564 | ] 565 | 566 | 567 | class RECV_EVENT_WEATHER_MODE(RECV_EVENT): 568 | # No event specific data - the new weather mode is in the base structure dwData member. 569 | _fields_ = [ 570 | ] 571 | 572 | 573 | # SIMCONNECT_RECV_FACILITIES_LIST 574 | class RECV_FACILITIES_LIST(RECV): 575 | _fields_ = [ 576 | ("dwRequestID", DWORD), 577 | ("dwArraySize", DWORD), 578 | ("dwEntryNumber", DWORD), # when the array of items is too big for one send, which send this is (0..dwOutOf-1) 579 | ("dwOutOf", DWORD), # total number of transmissions the list is chopped into 580 | ] 581 | 582 | 583 | # SIMCONNECT_DATA_FACILITY_AIRPORT 584 | class DATA_FACILITY_AIRPORT(Struct1): 585 | _fields_ = [ 586 | ("Icao", c_char * 9), # ICAO of the object 587 | ("Latitude", c_double), # degrees 588 | ("Longitude", c_double), # degrees 589 | ("Altitude", c_double), # meters 590 | ] 591 | 592 | 593 | # SIMCONNECT_RECV_AIRPORT_LIST 594 | class RECV_AIRPORT_LIST(RECV_FACILITIES_LIST): 595 | _fields_ = [ 596 | ("rgData", DATA_FACILITY_AIRPORT * 1), 597 | ] 598 | 599 | 600 | 601 | # SIMCONNECT_DATA_FACILITY_WAYPOINT 602 | class DATA_FACILITY_WAYPOINT(DATA_FACILITY_AIRPORT): 603 | _fields_ = [ 604 | ("fMagVar", c_float), # Magvar in degrees 605 | ] 606 | 607 | 608 | # SIMCONNECT_RECV_WAYPOINT_LIST 609 | class RECV_WAYPOINT_LIST(RECV_FACILITIES_LIST): 610 | _fields_ = [ 611 | ("rgData", DATA_FACILITY_WAYPOINT * 1), 612 | ] 613 | 614 | 615 | # SIMCONNECT_DATA_FACILITY_NDB 616 | class DATA_FACILITY_NDB(DATA_FACILITY_WAYPOINT): 617 | _fields_ = [ 618 | ("fFrequency", DWORD), # frequency in Hz 619 | ] 620 | 621 | 622 | # SIMCONNECT_RECV_NDB_LIST 623 | class RECV_NDB_LIST(RECV_FACILITIES_LIST): 624 | _fields_ = [ 625 | ("rgData", DATA_FACILITY_NDB * 1), 626 | ] 627 | 628 | 629 | # SIMCONNECT_DATA_FACILITY_VOR 630 | class DATA_FACILITY_VOR(DATA_FACILITY_NDB): 631 | _fields_ = [ 632 | ("Flags", DWORD), # SIMCONNECT_VOR_FLAGS 633 | ("fLocalizer", c_float), # Localizer in degrees 634 | ("GlideLat", c_double), # Glide Slope Location (deg, deg, meters) 635 | ("GlideLon", c_double), 636 | ("GlideAlt", c_double), 637 | ("fGlideSlopeAngle", c_float), # Glide Slope in degrees 638 | ] 639 | 640 | 641 | # SIMCONNECT_RECV_VOR_LIST 642 | class RECV_VOR_LIST(RECV_FACILITIES_LIST): 643 | _fields_ = [ 644 | ("rgData", DATA_FACILITY_VOR * 1), 645 | ] 646 | 647 | # 632 "SimConnect.h" 648 | # SIMCONNECT_DATATYPE_INITPOSITION 649 | class DATA_INITPOSITION(Struct1): 650 | _fields_ = [ 651 | ("Latitude", c_double), # degrees 652 | ("Longitude", c_double), # degrees 653 | ("Altitude", c_double), # feet 654 | ("Pitch", c_double), # degrees 655 | ("Bank", c_double), # degrees 656 | ("Heading", c_double), # degrees 657 | ("OnGround", DWORD), # 1=force to be on the ground 658 | ("Airspeed", DWORD), # knots 659 | ] 660 | 661 | 662 | 663 | # SIMCONNECT_DATATYPE_MARKERSTATE 664 | class DATA_MARKERSTATE(Struct1): 665 | _fields_ = [ 666 | ("szMarkerName", c_char * 64), 667 | ("dwMarkerState", DWORD), 668 | ] 669 | 670 | 671 | # SIMCONNECT_DATATYPE_WAYPOINT 672 | class DATA_WAYPOINT(Struct1): 673 | _fields_ = [ 674 | ("Latitude", c_double), # degrees 675 | ("Longitude", c_double), # degrees 676 | ("Altitude", c_double), # feet 677 | ("Flags", c_long), 678 | ("ktsSpeed", c_double), # knots 679 | ("percentThrottle", c_double), 680 | ] 681 | 682 | 683 | # SIMCONNECT_DATA_LATLONALT 684 | class DATA_LATLONALT(Struct1): 685 | _fields_ = [ 686 | ("Latitude", c_double), 687 | ("Longitude", c_double), 688 | ("Altitude", c_double), 689 | ] 690 | 691 | 692 | # SIMCONNECT_DATA_XYZ 693 | class DATA_XYZ(Struct1): 694 | _fields_ = [ 695 | ("x", c_double), 696 | ("y", c_double), 697 | ("z", c_double), 698 | ] 699 | 700 | 701 | #pragma pack(pop) 702 | 703 | # ---------------------------------------------------------------------------- 704 | # End of Struct definitions 705 | # ---------------------------------------------------------------------------- 706 | 707 | # typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); 708 | DispatchProc = WINFUNCTYPE(None, POINTER(RECV), DWORD, c_void_p) 709 | # 703 "SimConnect.h" 710 | 711 | 712 | def _decls(dll): 713 | _ = dict() 714 | f = dll.SimConnect_MapClientEventToSimEvent 715 | f.restype = HRESULT 716 | f.argtypes = [ 717 | HANDLE, # HANDLE hSimConnect 718 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 719 | c_char_p, # const char * EventName = "" 720 | ] 721 | _['MapClientEventToSimEvent'] = f 722 | f = dll.SimConnect_TransmitClientEvent 723 | f.restype = HRESULT 724 | f.argtypes = [ 725 | HANDLE, # HANDLE hSimConnect 726 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 727 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 728 | DWORD, # DWORD dwData 729 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 730 | EVENT_FLAG, # SIMCONNECT_EVENT_FLAG Flags 731 | ] 732 | _['TransmitClientEvent'] = f 733 | f = dll.SimConnect_SetSystemEventState 734 | f.restype = HRESULT 735 | f.argtypes = [ 736 | HANDLE, # HANDLE hSimConnect 737 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 738 | STATE, # SIMCONNECT_STATE dwState 739 | ] 740 | _['SetSystemEventState'] = f 741 | f = dll.SimConnect_AddClientEventToNotificationGroup 742 | f.restype = HRESULT 743 | f.argtypes = [ 744 | HANDLE, # HANDLE hSimConnect 745 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 746 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 747 | c_bool, # BOOL bMaskable = FALSE 748 | ] 749 | _['AddClientEventToNotificationGroup'] = f 750 | f = dll.SimConnect_RemoveClientEvent 751 | f.restype = HRESULT 752 | f.argtypes = [ 753 | HANDLE, # HANDLE hSimConnect 754 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 755 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 756 | ] 757 | _['RemoveClientEvent'] = f 758 | f = dll.SimConnect_SetNotificationGroupPriority 759 | f.restype = HRESULT 760 | f.argtypes = [ 761 | HANDLE, # HANDLE hSimConnect 762 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 763 | DWORD, # DWORD uPriority 764 | ] 765 | _['SetNotificationGroupPriority'] = f 766 | f = dll.SimConnect_ClearNotificationGroup 767 | f.restype = HRESULT 768 | f.argtypes = [ 769 | HANDLE, # HANDLE hSimConnect 770 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 771 | ] 772 | _['ClearNotificationGroup'] = f 773 | f = dll.SimConnect_RequestNotificationGroup 774 | f.restype = HRESULT 775 | f.argtypes = [ 776 | HANDLE, # HANDLE hSimConnect 777 | NOTIFICATION_GROUP_ID, # SIMCONNECT_NOTIFICATION_GROUP_ID GroupID 778 | DWORD, # DWORD dwReserved = 0 779 | DWORD, # DWORD Flags = 0 780 | ] 781 | _['RequestNotificationGroup'] = f 782 | f = dll.SimConnect_AddToDataDefinition 783 | f.restype = HRESULT 784 | f.argtypes = [ 785 | HANDLE, # HANDLE hSimConnect 786 | DATA_DEFINITION_ID, # SIMCONNECT_DATA_DEFINITION_ID DefineID 787 | c_char_p, # const char * DatumName 788 | c_char_p, # const char * UnitsName 789 | DATATYPE, # SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64 790 | c_float, # float fEpsilon = 0 791 | DWORD, # DWORD DatumID = SIMCONNECT_UNUSED 792 | ] 793 | _['AddToDataDefinition'] = f 794 | f = dll.SimConnect_ClearDataDefinition 795 | f.restype = HRESULT 796 | f.argtypes = [ 797 | HANDLE, # HANDLE hSimConnect 798 | DATA_DEFINITION_ID, # SIMCONNECT_DATA_DEFINITION_ID DefineID 799 | ] 800 | _['ClearDataDefinition'] = f 801 | f = dll.SimConnect_RequestDataOnSimObject 802 | f.restype = HRESULT 803 | f.argtypes = [ 804 | HANDLE, # HANDLE hSimConnect 805 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 806 | DATA_DEFINITION_ID, # SIMCONNECT_DATA_DEFINITION_ID DefineID 807 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 808 | PERIOD, # SIMCONNECT_PERIOD Period 809 | DATA_REQUEST_FLAG, # SIMCONNECT_DATA_REQUEST_FLAG Flags = 0 810 | DWORD, # DWORD origin = 0 811 | DWORD, # DWORD interval = 0 812 | DWORD, # DWORD limit = 0 813 | ] 814 | _['RequestDataOnSimObject'] = f 815 | f = dll.SimConnect_RequestDataOnSimObjectType 816 | f.restype = HRESULT 817 | f.argtypes = [ 818 | HANDLE, # HANDLE hSimConnect 819 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 820 | DATA_DEFINITION_ID, # SIMCONNECT_DATA_DEFINITION_ID DefineID 821 | DWORD, # DWORD dwRadiusMeters 822 | SIMOBJECT_TYPE, # SIMCONNECT_SIMOBJECT_TYPE type 823 | ] 824 | _['RequestDataOnSimObjectType'] = f 825 | f = dll.SimConnect_SetDataOnSimObject 826 | f.restype = HRESULT 827 | f.argtypes = [ 828 | HANDLE, # HANDLE hSimConnect 829 | DATA_DEFINITION_ID, # SIMCONNECT_DATA_DEFINITION_ID DefineID 830 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 831 | DATA_SET_FLAG, # SIMCONNECT_DATA_SET_FLAG Flags 832 | DWORD, # DWORD ArrayCount 833 | DWORD, # DWORD cbUnitSize 834 | c_void_p, # void * pDataSet 835 | ] 836 | _['SetDataOnSimObject'] = f 837 | f = dll.SimConnect_MapInputEventToClientEvent 838 | f.restype = HRESULT 839 | f.argtypes = [ 840 | HANDLE, # HANDLE hSimConnect 841 | INPUT_GROUP_ID, # SIMCONNECT_INPUT_GROUP_ID GroupID 842 | c_char_p, # const char * szInputDefinition 843 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID DownEventID 844 | DWORD, # DWORD DownValue = 0 845 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID 846 | ] 847 | _['MapInputEventToClientEvent'] = f 848 | f = dll.SimConnect_SetInputGroupPriority 849 | f.restype = HRESULT 850 | f.argtypes = [ 851 | HANDLE, # HANDLE hSimConnect 852 | INPUT_GROUP_ID, # SIMCONNECT_INPUT_GROUP_ID GroupID 853 | DWORD, # DWORD uPriority 854 | ] 855 | _['SetInputGroupPriority'] = f 856 | f = dll.SimConnect_RemoveInputEvent 857 | f.restype = HRESULT 858 | f.argtypes = [ 859 | HANDLE, # HANDLE hSimConnect 860 | INPUT_GROUP_ID, # SIMCONNECT_INPUT_GROUP_ID GroupID 861 | c_char_p, # const char * szInputDefinition 862 | ] 863 | _['RemoveInputEvent'] = f 864 | f = dll.SimConnect_ClearInputGroup 865 | f.restype = HRESULT 866 | f.argtypes = [ 867 | HANDLE, # HANDLE hSimConnect 868 | INPUT_GROUP_ID, # SIMCONNECT_INPUT_GROUP_ID GroupID 869 | ] 870 | _['ClearInputGroup'] = f 871 | f = dll.SimConnect_SetInputGroupState 872 | f.restype = HRESULT 873 | f.argtypes = [ 874 | HANDLE, # HANDLE hSimConnect 875 | INPUT_GROUP_ID, # SIMCONNECT_INPUT_GROUP_ID GroupID 876 | DWORD, # DWORD dwState 877 | ] 878 | _['SetInputGroupState'] = f 879 | f = dll.SimConnect_RequestReservedKey 880 | f.restype = HRESULT 881 | f.argtypes = [ 882 | HANDLE, # HANDLE hSimConnect 883 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 884 | c_char_p, # const char * szKeyChoice1 = "" 885 | c_char_p, # const char * szKeyChoice2 = "" 886 | c_char_p, # const char * szKeyChoice3 = "" 887 | ] 888 | _['RequestReservedKey'] = f 889 | f = dll.SimConnect_SubscribeToSystemEvent 890 | f.restype = HRESULT 891 | f.argtypes = [ 892 | HANDLE, # HANDLE hSimConnect 893 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 894 | c_char_p, # const char * SystemEventName 895 | ] 896 | _['SubscribeToSystemEvent'] = f 897 | f = dll.SimConnect_UnsubscribeFromSystemEvent 898 | f.restype = HRESULT 899 | f.argtypes = [ 900 | HANDLE, # HANDLE hSimConnect 901 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 902 | ] 903 | _['UnsubscribeFromSystemEvent'] = f 904 | f = dll.SimConnect_WeatherRequestInterpolatedObservation 905 | f.restype = HRESULT 906 | f.argtypes = [ 907 | HANDLE, # HANDLE hSimConnect 908 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 909 | c_float, # float lat 910 | c_float, # float lon 911 | c_float, # float alt 912 | ] 913 | _['WeatherRequestInterpolatedObservation'] = f 914 | f = dll.SimConnect_WeatherRequestObservationAtStation 915 | f.restype = HRESULT 916 | f.argtypes = [ 917 | HANDLE, # HANDLE hSimConnect 918 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 919 | c_char_p, # const char * szICAO 920 | ] 921 | _['WeatherRequestObservationAtStation'] = f 922 | f = dll.SimConnect_WeatherRequestObservationAtNearestStation 923 | f.restype = HRESULT 924 | f.argtypes = [ 925 | HANDLE, # HANDLE hSimConnect 926 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 927 | c_float, # float lat 928 | c_float, # float lon 929 | ] 930 | _['WeatherRequestObservationAtNearestStation'] = f 931 | f = dll.SimConnect_WeatherCreateStation 932 | f.restype = HRESULT 933 | f.argtypes = [ 934 | HANDLE, # HANDLE hSimConnect 935 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 936 | c_char_p, # const char * szICAO 937 | c_char_p, # const char * szName 938 | c_float, # float lat 939 | c_float, # float lon 940 | c_float, # float alt 941 | ] 942 | _['WeatherCreateStation'] = f 943 | f = dll.SimConnect_WeatherRemoveStation 944 | f.restype = HRESULT 945 | f.argtypes = [ 946 | HANDLE, # HANDLE hSimConnect 947 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 948 | c_char_p, # const char * szICAO 949 | ] 950 | _['WeatherRemoveStation'] = f 951 | f = dll.SimConnect_WeatherSetObservation 952 | f.restype = HRESULT 953 | f.argtypes = [ 954 | HANDLE, # HANDLE hSimConnect 955 | DWORD, # DWORD Seconds 956 | c_char_p, # const char * szMETAR 957 | ] 958 | _['WeatherSetObservation'] = f 959 | f = dll.SimConnect_WeatherSetModeServer 960 | f.restype = HRESULT 961 | f.argtypes = [ 962 | HANDLE, # HANDLE hSimConnect 963 | DWORD, # DWORD dwPort 964 | DWORD, # DWORD dwSeconds 965 | ] 966 | _['WeatherSetModeServer'] = f 967 | f = dll.SimConnect_WeatherSetModeTheme 968 | f.restype = HRESULT 969 | f.argtypes = [ 970 | HANDLE, # HANDLE hSimConnect 971 | c_char_p, # const char * szThemeName 972 | ] 973 | _['WeatherSetModeTheme'] = f 974 | f = dll.SimConnect_WeatherSetModeGlobal 975 | f.restype = HRESULT 976 | f.argtypes = [ 977 | HANDLE, # HANDLE hSimConnect 978 | ] 979 | _['WeatherSetModeGlobal'] = f 980 | f = dll.SimConnect_WeatherSetModeCustom 981 | f.restype = HRESULT 982 | f.argtypes = [ 983 | HANDLE, # HANDLE hSimConnect 984 | ] 985 | _['WeatherSetModeCustom'] = f 986 | f = dll.SimConnect_WeatherSetDynamicUpdateRate 987 | f.restype = HRESULT 988 | f.argtypes = [ 989 | HANDLE, # HANDLE hSimConnect 990 | DWORD, # DWORD dwRate 991 | ] 992 | _['WeatherSetDynamicUpdateRate'] = f 993 | f = dll.SimConnect_WeatherRequestCloudState 994 | f.restype = HRESULT 995 | f.argtypes = [ 996 | HANDLE, # HANDLE hSimConnect 997 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 998 | c_float, # float minLat 999 | c_float, # float minLon 1000 | c_float, # float minAlt 1001 | c_float, # float maxLat 1002 | c_float, # float maxLon 1003 | c_float, # float maxAlt 1004 | DWORD, # DWORD dwFlags = 0 1005 | ] 1006 | _['WeatherRequestCloudState'] = f 1007 | f = dll.SimConnect_WeatherCreateThermal 1008 | f.restype = HRESULT 1009 | f.argtypes = [ 1010 | HANDLE, # HANDLE hSimConnect 1011 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1012 | c_float, # float lat 1013 | c_float, # float lon 1014 | c_float, # float alt 1015 | c_float, # float radius 1016 | c_float, # float height 1017 | c_float, # float coreRate = 3.0f 1018 | c_float, # float coreTurbulence = 0.05f 1019 | c_float, # float sinkRate = 3.0f 1020 | c_float, # float sinkTurbulence = 0.2f 1021 | c_float, # float coreSize = 0.4f 1022 | c_float, # float coreTransitionSize = 0.1f 1023 | c_float, # float sinkLayerSize = 0.4f 1024 | c_float, # float sinkTransitionSize = 0.1f 1025 | ] 1026 | _['WeatherCreateThermal'] = f 1027 | f = dll.SimConnect_WeatherRemoveThermal 1028 | f.restype = HRESULT 1029 | f.argtypes = [ 1030 | HANDLE, # HANDLE hSimConnect 1031 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 1032 | ] 1033 | _['WeatherRemoveThermal'] = f 1034 | f = dll.SimConnect_AICreateParkedATCAircraft 1035 | f.restype = HRESULT 1036 | f.argtypes = [ 1037 | HANDLE, # HANDLE hSimConnect 1038 | c_char_p, # const char * szContainerTitle 1039 | c_char_p, # const char * szTailNumber 1040 | c_char_p, # const char * szAirportID 1041 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1042 | ] 1043 | _['AICreateParkedATCAircraft'] = f 1044 | f = dll.SimConnect_AICreateEnrouteATCAircraft 1045 | f.restype = HRESULT 1046 | f.argtypes = [ 1047 | HANDLE, # HANDLE hSimConnect 1048 | c_char_p, # const char * szContainerTitle 1049 | c_char_p, # const char * szTailNumber 1050 | c_int, # int iFlightNumber 1051 | c_char_p, # const char * szFlightPlanPath 1052 | c_double, # double dFlightPlanPosition 1053 | c_bool, # BOOL bTouchAndGo 1054 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1055 | ] 1056 | _['AICreateEnrouteATCAircraft'] = f 1057 | f = dll.SimConnect_AICreateNonATCAircraft 1058 | f.restype = HRESULT 1059 | f.argtypes = [ 1060 | HANDLE, # HANDLE hSimConnect 1061 | c_char_p, # const char * szContainerTitle 1062 | c_char_p, # const char * szTailNumber 1063 | DATA_INITPOSITION, # SIMCONNECT_DATA_INITPOSITION InitPos 1064 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1065 | ] 1066 | _['AICreateNonATCAircraft'] = f 1067 | f = dll.SimConnect_AICreateSimulatedObject 1068 | f.restype = HRESULT 1069 | f.argtypes = [ 1070 | HANDLE, # HANDLE hSimConnect 1071 | c_char_p, # const char * szContainerTitle 1072 | DATA_INITPOSITION, # SIMCONNECT_DATA_INITPOSITION InitPos 1073 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1074 | ] 1075 | _['AICreateSimulatedObject'] = f 1076 | f = dll.SimConnect_AIReleaseControl 1077 | f.restype = HRESULT 1078 | f.argtypes = [ 1079 | HANDLE, # HANDLE hSimConnect 1080 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 1081 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1082 | ] 1083 | _['AIReleaseControl'] = f 1084 | f = dll.SimConnect_AIRemoveObject 1085 | f.restype = HRESULT 1086 | f.argtypes = [ 1087 | HANDLE, # HANDLE hSimConnect 1088 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 1089 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1090 | ] 1091 | _['AIRemoveObject'] = f 1092 | f = dll.SimConnect_AISetAircraftFlightPlan 1093 | f.restype = HRESULT 1094 | f.argtypes = [ 1095 | HANDLE, # HANDLE hSimConnect 1096 | OBJECT_ID, # SIMCONNECT_OBJECT_ID ObjectID 1097 | c_char_p, # const char * szFlightPlanPath 1098 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1099 | ] 1100 | _['AISetAircraftFlightPlan'] = f 1101 | f = dll.SimConnect_ExecuteMissionAction 1102 | f.restype = HRESULT 1103 | f.argtypes = [ 1104 | HANDLE, # HANDLE hSimConnect 1105 | GUID, # const GUID guidInstanceId 1106 | ] 1107 | _['ExecuteMissionAction'] = f 1108 | f = dll.SimConnect_CompleteCustomMissionAction 1109 | f.restype = HRESULT 1110 | f.argtypes = [ 1111 | HANDLE, # HANDLE hSimConnect 1112 | GUID, # const GUID guidInstanceId 1113 | ] 1114 | _['CompleteCustomMissionAction'] = f 1115 | f = dll.SimConnect_Close 1116 | f.restype = HRESULT 1117 | f.argtypes = [ 1118 | HANDLE, # HANDLE hSimConnect 1119 | ] 1120 | _['Close'] = f 1121 | f = dll.SimConnect_RetrieveString 1122 | f.restype = HRESULT 1123 | f.argtypes = [ 1124 | POINTER(RECV), # SIMCONNECT_RECV * pData 1125 | DWORD, # DWORD cbData 1126 | c_void_p, # void * pStringV 1127 | POINTER(c_char_p), # char ** pszString 1128 | POINTER(DWORD), # DWORD * pcbString 1129 | ] 1130 | _['RetrieveString'] = f 1131 | f = dll.SimConnect_GetLastSentPacketID 1132 | f.restype = HRESULT 1133 | f.argtypes = [ 1134 | HANDLE, # HANDLE hSimConnect 1135 | POINTER(DWORD), # DWORD * pdwError 1136 | ] 1137 | _['GetLastSentPacketID'] = f 1138 | f = dll.SimConnect_Open 1139 | f.restype = HRESULT 1140 | f.argtypes = [ 1141 | POINTER(HANDLE), # HANDLE * phSimConnect 1142 | LPCSTR, # LPCSTR szName 1143 | HWND, # HWND hWnd 1144 | DWORD, # DWORD UserEventWin32 1145 | HANDLE, # HANDLE hEventHandle 1146 | DWORD, # DWORD ConfigIndex 1147 | ] 1148 | _['Open'] = f 1149 | f = dll.SimConnect_CallDispatch 1150 | f.restype = HRESULT 1151 | f.argtypes = [ 1152 | HANDLE, # HANDLE hSimConnect 1153 | DispatchProc, # DispatchProc pfcnDispatch 1154 | c_void_p, # void * pContext 1155 | ] 1156 | _['CallDispatch'] = f 1157 | f = dll.SimConnect_GetNextDispatch 1158 | f.restype = HRESULT 1159 | f.argtypes = [ 1160 | HANDLE, # HANDLE hSimConnect 1161 | POINTER(POINTER(RECV)), # SIMCONNECT_RECV ** ppData 1162 | POINTER(DWORD), # DWORD * pcbData 1163 | ] 1164 | _['GetNextDispatch'] = f 1165 | f = dll.SimConnect_RequestResponseTimes 1166 | f.restype = HRESULT 1167 | f.argtypes = [ 1168 | HANDLE, # HANDLE hSimConnect 1169 | DWORD, # DWORD nCount 1170 | c_float_p, # float * fElapsedSeconds 1171 | ] 1172 | _['RequestResponseTimes'] = f 1173 | f = dll.SimConnect_InsertString 1174 | f.restype = HRESULT 1175 | f.argtypes = [ 1176 | c_char_p, # char * pDest 1177 | DWORD, # DWORD cbDest 1178 | POINTER(c_void_p), # void ** ppEnd 1179 | POINTER(DWORD), # DWORD * pcbStringV 1180 | c_char_p, # const char * pSource 1181 | ] 1182 | _['InsertString'] = f 1183 | f = dll.SimConnect_CameraSetRelative6DOF 1184 | f.restype = HRESULT 1185 | f.argtypes = [ 1186 | HANDLE, # HANDLE hSimConnect 1187 | c_float, # float fDeltaX 1188 | c_float, # float fDeltaY 1189 | c_float, # float fDeltaZ 1190 | c_float, # float fPitchDeg 1191 | c_float, # float fBankDeg 1192 | c_float, # float fHeadingDeg 1193 | ] 1194 | _['CameraSetRelative6DOF'] = f 1195 | f = dll.SimConnect_MenuAddItem 1196 | f.restype = HRESULT 1197 | f.argtypes = [ 1198 | HANDLE, # HANDLE hSimConnect 1199 | c_char_p, # const char * szMenuItem 1200 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID MenuEventID 1201 | DWORD, # DWORD dwData 1202 | ] 1203 | _['MenuAddItem'] = f 1204 | f = dll.SimConnect_MenuDeleteItem 1205 | f.restype = HRESULT 1206 | f.argtypes = [ 1207 | HANDLE, # HANDLE hSimConnect 1208 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID MenuEventID 1209 | ] 1210 | _['MenuDeleteItem'] = f 1211 | f = dll.SimConnect_MenuAddSubItem 1212 | f.restype = HRESULT 1213 | f.argtypes = [ 1214 | HANDLE, # HANDLE hSimConnect 1215 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID MenuEventID 1216 | c_char_p, # const char * szMenuItem 1217 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID 1218 | DWORD, # DWORD dwData 1219 | ] 1220 | _['MenuAddSubItem'] = f 1221 | f = dll.SimConnect_MenuDeleteSubItem 1222 | f.restype = HRESULT 1223 | f.argtypes = [ 1224 | HANDLE, # HANDLE hSimConnect 1225 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID MenuEventID 1226 | CLIENT_EVENT_ID, # const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID 1227 | ] 1228 | _['MenuDeleteSubItem'] = f 1229 | f = dll.SimConnect_RequestSystemState 1230 | f.restype = HRESULT 1231 | f.argtypes = [ 1232 | HANDLE, # HANDLE hSimConnect 1233 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1234 | c_char_p, # const char * szState 1235 | ] 1236 | _['RequestSystemState'] = f 1237 | f = dll.SimConnect_SetSystemState 1238 | f.restype = HRESULT 1239 | f.argtypes = [ 1240 | HANDLE, # HANDLE hSimConnect 1241 | c_char_p, # const char * szState 1242 | DWORD, # DWORD dwInteger 1243 | c_float, # float fFloat 1244 | c_char_p, # const char * szString 1245 | ] 1246 | _['SetSystemState'] = f 1247 | f = dll.SimConnect_MapClientDataNameToID 1248 | f.restype = HRESULT 1249 | f.argtypes = [ 1250 | HANDLE, # HANDLE hSimConnect 1251 | c_char_p, # const char * szClientDataName 1252 | CLIENT_DATA_ID, # SIMCONNECT_CLIENT_DATA_ID ClientDataID 1253 | ] 1254 | _['MapClientDataNameToID'] = f 1255 | f = dll.SimConnect_CreateClientData 1256 | f.restype = HRESULT 1257 | f.argtypes = [ 1258 | HANDLE, # HANDLE hSimConnect 1259 | CLIENT_DATA_ID, # SIMCONNECT_CLIENT_DATA_ID ClientDataID 1260 | DWORD, # DWORD dwSize 1261 | CREATE_CLIENT_DATA_FLAG, # SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags 1262 | ] 1263 | _['CreateClientData'] = f 1264 | f = dll.SimConnect_AddToClientDataDefinition 1265 | f.restype = HRESULT 1266 | f.argtypes = [ 1267 | HANDLE, # HANDLE hSimConnect 1268 | CLIENT_DATA_DEFINITION_ID, # SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID 1269 | DWORD, # DWORD dwOffset 1270 | DWORD, # DWORD dwSizeOrType 1271 | c_float, # float fEpsilon = 0 1272 | DWORD, # DWORD DatumID = SIMCONNECT_UNUSED 1273 | ] 1274 | _['AddToClientDataDefinition'] = f 1275 | f = dll.SimConnect_ClearClientDataDefinition 1276 | f.restype = HRESULT 1277 | f.argtypes = [ 1278 | HANDLE, # HANDLE hSimConnect 1279 | CLIENT_DATA_DEFINITION_ID, # SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID 1280 | ] 1281 | _['ClearClientDataDefinition'] = f 1282 | f = dll.SimConnect_RequestClientData 1283 | f.restype = HRESULT 1284 | f.argtypes = [ 1285 | HANDLE, # HANDLE hSimConnect 1286 | CLIENT_DATA_ID, # SIMCONNECT_CLIENT_DATA_ID ClientDataID 1287 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1288 | CLIENT_DATA_DEFINITION_ID, # SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID 1289 | CLIENT_DATA_PERIOD, # SIMCONNECT_CLIENT_DATA_PERIOD Period = SIMCONNECT_CLIENT_DATA_PERIOD_ONCE 1290 | CLIENT_DATA_REQUEST_FLAG, # SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags = 0 1291 | DWORD, # DWORD origin = 0 1292 | DWORD, # DWORD interval = 0 1293 | DWORD, # DWORD limit = 0 1294 | ] 1295 | _['RequestClientData'] = f 1296 | f = dll.SimConnect_SetClientData 1297 | f.restype = HRESULT 1298 | f.argtypes = [ 1299 | HANDLE, # HANDLE hSimConnect 1300 | CLIENT_DATA_ID, # SIMCONNECT_CLIENT_DATA_ID ClientDataID 1301 | CLIENT_DATA_DEFINITION_ID, # SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID 1302 | CLIENT_DATA_SET_FLAG, # SIMCONNECT_CLIENT_DATA_SET_FLAG Flags 1303 | DWORD, # DWORD dwReserved 1304 | DWORD, # DWORD cbUnitSize 1305 | c_void_p, # void * pDataSet 1306 | ] 1307 | _['SetClientData'] = f 1308 | f = dll.SimConnect_FlightLoad 1309 | f.restype = HRESULT 1310 | f.argtypes = [ 1311 | HANDLE, # HANDLE hSimConnect 1312 | c_char_p, # const char * szFileName 1313 | ] 1314 | _['FlightLoad'] = f 1315 | f = dll.SimConnect_FlightSave 1316 | f.restype = HRESULT 1317 | f.argtypes = [ 1318 | HANDLE, # HANDLE hSimConnect 1319 | c_char_p, # const char * szFileName 1320 | c_char_p, # const char * szTitle 1321 | c_char_p, # const char * szDescription 1322 | DWORD, # DWORD Flags 1323 | ] 1324 | _['FlightSave'] = f 1325 | f = dll.SimConnect_FlightPlanLoad 1326 | f.restype = HRESULT 1327 | f.argtypes = [ 1328 | HANDLE, # HANDLE hSimConnect 1329 | c_char_p, # const char * szFileName 1330 | ] 1331 | _['FlightPlanLoad'] = f 1332 | f = dll.SimConnect_Text 1333 | f.restype = HRESULT 1334 | f.argtypes = [ 1335 | HANDLE, # HANDLE hSimConnect 1336 | TEXT_TYPE, # SIMCONNECT_TEXT_TYPE type 1337 | c_float, # float fTimeSeconds 1338 | CLIENT_EVENT_ID, # SIMCONNECT_CLIENT_EVENT_ID EventID 1339 | DWORD, # DWORD cbUnitSize 1340 | c_void_p, # void * pDataSet 1341 | ] 1342 | _['Text'] = f 1343 | f = dll.SimConnect_SubscribeToFacilities 1344 | f.restype = HRESULT 1345 | f.argtypes = [ 1346 | HANDLE, # HANDLE hSimConnect 1347 | FACILITY_LIST_TYPE, # SIMCONNECT_FACILITY_LIST_TYPE type 1348 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1349 | ] 1350 | _['SubscribeToFacilities'] = f 1351 | f = dll.SimConnect_UnsubscribeToFacilities 1352 | f.restype = HRESULT 1353 | f.argtypes = [ 1354 | HANDLE, # HANDLE hSimConnect 1355 | FACILITY_LIST_TYPE, # SIMCONNECT_FACILITY_LIST_TYPE type 1356 | ] 1357 | _['UnsubscribeToFacilities'] = f 1358 | f = dll.SimConnect_RequestFacilitiesList 1359 | f.restype = HRESULT 1360 | f.argtypes = [ 1361 | HANDLE, # HANDLE hSimConnect 1362 | FACILITY_LIST_TYPE, # SIMCONNECT_FACILITY_LIST_TYPE type 1363 | DATA_REQUEST_ID, # SIMCONNECT_DATA_REQUEST_ID RequestID 1364 | ] 1365 | _['RequestFacilitiesList'] = f 1366 | return _ 1367 | -------------------------------------------------------------------------------- /simconnect/scvars.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List, Dict, Any 2 | import re 3 | import os 4 | import json 5 | import logging 6 | from difflib import get_close_matches 7 | from .scdefs import DATATYPE_INT32, DATATYPE_FLOAT64, DATATYPE_STRING256 8 | 9 | 10 | def validate_simvar(name: str, settable: bool) -> Optional[Dict[str, Any]]: 11 | """Match a simvar name and settable flag to known variables""" 12 | base = _namestd(name) 13 | sv = SIMVARS.get(base, {}) 14 | if not sv: 15 | logging.warning(f"SimConnect: unrecognized simvar '{base}', {_closemsg(base, SIMVARS)}") 16 | else: 17 | if sv['indexed'] and ':' not in name: 18 | logging.warning(f"SimConnect: expected indexed simvar, e.g. {name}:3") 19 | if settable and not sv.get('settable'): 20 | logging.warning(f"SimConnect: simvar {name} is not settable") 21 | return sv 22 | 23 | 24 | def validate_event(event) -> str: 25 | s = _eventstd(event) 26 | if s not in EVENTS: 27 | logging.warn(f"Simconnect: Unrecognized event {event}") 28 | return s 29 | 30 | 31 | def validate_units(name: str, units: Optional[str], simvar: Optional[Dict[str, Any]]) -> str: 32 | # lookup default units if not provided, note units='' is valid 33 | if units is None: 34 | if simvar is not None: 35 | # If not specified, try inferring units from variable 36 | ustd = simvar.get('units_std', '') 37 | else: 38 | ustd = '' 39 | if not ustd: 40 | logging.warning(f"SimConnect: no units specified or inferred for {name}") 41 | elif units == '': 42 | # deliberate empty string 43 | ustd = units 44 | else: 45 | # get the canonical unit name 46 | ustd = _unitstd(units)[0] 47 | if ustd in UNITS: 48 | ustd = UNITS[ustd]['name_std'] 49 | else: 50 | possibilities: List[str] = [] 51 | if simvar: 52 | possibilities = DIMENSIONS.get(simvar['dimensions']) 53 | if not possibilities: 54 | possibilities = [u['name_std'] for u in UNITS.values()] 55 | msg = _closemsg(ustd, possibilities) 56 | logging.warning(f"SimConnect: unrecognized units '{units}' for {name}, {msg}") 57 | return ustd 58 | 59 | 60 | def type_for_unit(unit: str) -> int: 61 | unit = unit.upper() 62 | if unit in UNITS: 63 | u = UNITS[unit] 64 | if u['dimensions'] == 'Miscellaneous Units': 65 | if u['name_std'] in ('Bool', 'Boolean', 'Enum', 'BCO16', 'mask', 'flags'): 66 | return DATATYPE_INT32 67 | elif u['name_std'] == 'string': 68 | return DATATYPE_STRING256 69 | else: 70 | warn = f"SimConnect: unrecognized Miscellaneous Unit in typefor({unit})" 71 | elif u['dimensions'] == 'Structs And Other Complex Units': 72 | warn = f"SimConnect: complex types not supported for {unit}" 73 | else: 74 | return DATATYPE_FLOAT64 75 | else: 76 | warn = f"SimConnect: unrecognized unit in typefor({unit})" 77 | 78 | logging.warning(warn + "; using float64 as fallback") 79 | return DATATYPE_FLOAT64 80 | 81 | 82 | def _closemsg(s, ss): 83 | xs = get_close_matches(s, ss) 84 | if xs: 85 | msg = f"perhaps one of {', '.join(xs)}?" 86 | else: 87 | options = (ss[:3] + ['...']) if len(ss) > 3 else ss 88 | msg = f"found no similar options among: {', '.join(options)}" 89 | return msg 90 | 91 | 92 | def _namestd(s) -> str: 93 | return s.rsplit(':', 1)[0].upper().replace('_', ' ') 94 | 95 | 96 | def _unitstd(ss, canonical=True) -> List[str]: 97 | vs = [] 98 | ss = re.sub(r'^Struct:\n\s*', '', ss) 99 | for s in ss.split('\n')[0].split(','): 100 | s = s.strip().rstrip(':') 101 | if canonical: 102 | s = s.upper().replace('-', ' ').replace('_', ' ') 103 | s = re.sub(r'\s+PER\s+', '/', s) # "Feet per second" 104 | s = re.sub(r'\s*\([^()]+\)\s*', '', s) # "Feet (ft) / second" 105 | s = re.sub(r'\s*\([^)]+$', '', s) # "pounds per square inch (psi" 106 | s = s.replace('SCALAR', 'SCALER') 107 | s = s.replace('POUNDS/SQUARE FOOT', 'PSF') 108 | s = s.replace('POUND FORCE/SQUARE FOOT', 'PSF') 109 | s = s.replace('POUNDS/SQUARE INCH', 'PSI') 110 | s = s.replace('SLUGS/FEET SQUARED', 'SLUGS FEET SQUARED') 111 | s = s.replace('KILO PASCAL', 'KILOPASCAL') 112 | s = s.replace('FOOT POUNDS/SECOND', 'FT LB/SECOND') 113 | s = re.sub(r'^SIMCONNECT DATA\s+(.*?)(\s+STRUCT(URE)?)?$', r'\1', s) 114 | vs.append(s.strip()) 115 | return vs 116 | 117 | 118 | def _eventstd(s): 119 | return s.upper() 120 | 121 | 122 | # Load SDK definitions scraped from documentation, see ../scripts/scrapevars.py 123 | try: 124 | _scvars = json.load(open(os.path.join(os.path.dirname(__file__), 'scvars.json'))) 125 | except Exception: 126 | logging.warning('Failed to load scvars.json') 127 | _scvars = dict(SIMVARS={}, EVENTS={}, UNITS={}, DIMENSIONS={}) 128 | 129 | # Expose the standardized definitions scraped from docs 130 | SIMVARS = _scvars['VARIABLES'] 131 | EVENTS = _scvars['EVENTS'] 132 | UNITS = _scvars['UNITS'] 133 | DIMENSIONS = _scvars['DIMENSIONS'] 134 | -------------------------------------------------------------------------------- /simconnect/winstubs.py: -------------------------------------------------------------------------------- 1 | # hack to avoid simconnect import error on non-windows platform 2 | # allows us to run some supporting tools, but not simconnect SDK connection 3 | from ctypes import c_char, c_ushort, c_ulong, c_void_p, c_char_p 4 | 5 | 6 | HRESULT = c_ushort 7 | BYTE = c_char 8 | WORD = c_ushort 9 | DWORD = c_ulong 10 | HANDLE = c_void_p 11 | LPCSTR = c_char_p 12 | HWND = c_void_p 13 | 14 | 15 | def WINFUNCTYPE(*args, **kwargs): 16 | pass 17 | 18 | 19 | class windll: 20 | def LoadLibrary(self, *args, **kwargs): 21 | pass 22 | --------------------------------------------------------------------------------