Main jSimConnect package
This package contains main data structures to create and manage a
jSimConnect connection. To handle responses and received data from
the server, see classes in recv package.
SimConnect protocol internals
SimConnect uses TCP/IP communication, even for localhost and intra-process
communication. Although this design could have severe drawbacks, it
is far easier to implement and allows complete distributing, since
application will have the same behavior running from remote host or
launched as FSX DLLs.
To increase performance for local communications, all firewalls or
traffic inspector software should be disabled.
Rule of the thumb
- Every function of the simconnect API synchronously sends a packet
formed by a 16 bytes
header and all arguments concatened in the order of the declaration
- Every received packet data is passed without change to the dispatch proc (the
packet format is directly known from SIMCONNECT_RECV structures.
Exceptions are the {@link flightsim.simconnect.SimConnect#requestResponseTimes} function that
does little logic (not implemented in jSimConnect) and the open function
that uses slightly differents arguments, but with the same packet header.
No forms of data acknowledgement are actually processed by the client library,
so the client application will receive all received data.
Format of sent packets
All integers sent, including headers, are in little-endian Intel format.
The 16-bytes header consists of 4 integer :
- 0 - int32 : total size in bytes of the packet (including header)
- 4 - int32 : protocol version. 0x2 for FSX original release; 0x3 for SP1, 0x4 for SP2
- 8 - int32 : packet type ID. Each function of the library has a predefined type,
usually numbered from 1 to 0x3F. The type is sent OR'ed with 0xF0000000
(unknown meaning).
- 12 - int32 : packet identifier : each packet has an unique identifier, which
is used to identify erroneous requests when the server sends back an exception.
Generally a sequence number.
Unless mentionned in the documentation, all strings are sent in ISO-8859-1
encoding, and padded up to 256 bytes. File name and paths are sent padded up to 260 bytes.
Even null references or empty strings are padded. Generally requests
have a fixed size, excepted for function that takes a pointer to byte array.
METAR strings are not padded.
Floating point numbers may be 32 bits or 64 bits long. Both types are
sent in IEEE 754 format.
Sucessful requests other than open are not acknowledged by the server.
The open packet has a slightly different format. It's format is the
following:
- bytes 0-16 : standard header (see above)
- 16 - char[256] : application name (standard 256 bytes long string, padded with zeros)
- 272 - int32 : unknown meaning (always 0)
- 276 - char : 0
- 277 - char : 'X' (ascii character)
- 278 - char : 'S'
- 279 - char : 'F'
- 280 - int32 : simconnect version major (eg 10)
- 284 - int32 : simconnect version minor (eg 0)
- 288 - int32 : simconnect build major (eg 61355)
- 292 - int32 : simconnect build minor (eg 0)
The server checks that simconnect version and build numbers are corresponding
to the protocol version. FSX RTM 'SP0' expects protocol version 2 and
60905.0 as build number. FSX SP1 use version 3 and build number 61355.0.
FSX SP0 does not verify version number, whereas SP1 needs "10.0" as
version.
Packet type IDs
function | packet type ID/ | |
Open | 0x1 |
QueryPerformanceCounter | 0x3 |
MapClientEventToSimEvent | 0x4 |
TransmitClientEvent | 0x5 |
SetSystemEventState | 0x6 |
AddClientEventToNotificationGroup | 0x07 |
RemoveClientEvent | 0x8 |
SetNotificationGroupPriority | 0x9 |
ClearNotificationGroup | 0xa |
RequestNotificationGroup | 0xb |
AddToDataDefinition | 0xc |
ClearDataDefinition | 0xd |
RequestDataOnSimObject | 0xe |
RequestDataOnSimObjectType | 0xf |
SetDataOnSimObject | 0x10 |
MapInputEventToClientEvent | 0x11 |
SetInputGroupPriority | 0x12 |
RemoveInputEvent | 0x13 |
ClearInputGroup | 0x14 |
SetInputGroupState | 0x15 |
RequestReservedKey | 0x16 |
SubscribeToSystemEvent | 0x17 |
UnsubscribeFromSystemEvent | 0x18 |
WeatherRequestInterpolatedObservation | 0x19 |
WeatherRequestObservationAtStation | 0x1A |
WeatherRequestObservationAtNearestStation | 0x1B |
WeatherCreateStation | 0x1C |
WeatherRemoveStation | 0x1D |
WeatherSetObservation | 0x1E |
WeatherSetModeServer | 0x1F |
WeatherSetModeTheme | 0x20 |
WeatherSetModeGlobal | 0x21 |
WeatherSetModeCustom | 0x22 |
WeatherSetDynamicUpdateRate | 0x23 |
WeatherRequestCloudState | 0x24 |
WeatherCreateThermal | 0x25 |
WeatherRemoveThermal | 0x26 |
AICreateParkedATCAircraft | 0x27 |
AICreateEnrouteATCAircraft | 0x28 |
AICreateNonATCAircraft | 0x29 |
AICreateSimulatedObject | 0x2A |
AIReleaseControl | 0x2B |
AIRemoveObject | 0x2C |
AISetAircraftFlightPlan | 0x2D |
ExecuteMissionAction | 0x2E |
CompleteCustomMissionAction | 0x2F |
CameraSetRelative6DOF | 0x30 |
MenuAddItem | 0x31 |
MenuDeleteItem | 0x32 |
MenuAddSubItem | 0x33 |
MenuDeleteSubItem | 0x34 |
RequestSystemState | 0x35 |
SetSystemState | 0x36 |
MapClientDataNameToID | 0x37 |
CreateClientData | 0x38 |
AddToClientDataDefinition | 0x39 |
ClearClientDataDefinition | 0x3A |
RequestClientData | 0x3B |
SetClientData | 0x3C |
FlightLoad | 0x3D |
FlightSave | 0x3E |
FlightPlanLoad | 0x3F |
Text | 0x40 |
SubscribeToFacilities | 0x41 |
UnSubscribeToFacilities | 0x42 |
RequestFacilitiesList | 0x43 |
The RequestClientData and AddToClientDataDefinition
have different prototypes in simconnect SP1. The check is done
by the server based on the protocol version.
Format of received packets
All received packets are sent to the DispatchProc, so their format
follow the definition of SIMCONNECT_RECV structure. The header is 12 bytes
long and is similar to sent packets:
- 0 - int32 : total size in bytes
- 4 - int32 : protocol version (0x2 or 0x3)
- 8 - int32 : packet type. see the numbers in the RECV_ID enumeration
The non-header datas that follows are flat representation of subclasses
of SIMCONNECT_RECV. Some may be of variable length (METAR, SimObjectData).
Networking
SimConnect use TCP/IP networking even when the application and FSX are
on the same machine, or in the same process (when client is launched
from DLL.xml). The server can be configured to listen on IPv4 or
IPv6 addresses, but the format of data transferred is the same.
When not port numbers are specified in server config file (SimConnect.XML),
it is chosen randomly (more frequently, unspecified port numbers in MS Windows
are chosen from 1024 and increasing at each request), but no
heuristic will work). If the scope in SimConnect.XML is defined to be local,
then the port number is posted in the registry database
in USER_ROOT\SOFTWARE\Microsoft Games\Flight Simulator\SimConnect_Port_IPv4
(or SimConnect_Port_IPv6 if used)
Implementing a simconnect client library in java
The SimConnect client library, although very simple, relies on non-portable
programming tricks: casting raw data array to structures, packing of
structures in memory, fixed endianness. These tricks are difficult, or
even impossible, to develop in strict OOP languages.
The managed implementation (C#) of the SimConnect library makes extensive
use of compiler-dependent instructions like explicit marshalling and structure
layout definitions. Such instructions are not available in the Java language.
To use java classes as data definitions, the programmer had to implement
all functions that transforms the content of classes from and to a byte array
(Standard serialization is NOT applicable). A useful API is
{@link java.nio.ByteBuffer} that provides functions to read/write integers and
floating point numbers. Note that a ByteBuffer is big endian by default
{@link java.nio.ByteBuffer#order()}. jSimConnect makes extensive use
of this class.
Another caveat is memory/cpu consumption. In the standard SimConnect implementation,
data from the network is directly casted to a pointer to a structure
of the right type. In jSimConnect, the data is wrapped first into
a temporary ByteBuffer, and then an instance of a subclass of {@link flightsim.simconnect.recv.RecvPacket}
is constructed. Add endianness transformation, 5-6 method calls for
each field, and overhead of allocating 2 objects for each received packets.
The result is not so awful since a lot of optimization lies in the JVM. I'm
always surprised of the performance of some bloated java code ;-).
However, jSimConnect is reasonnably not intended to run on the same
machine as FSX, because the total overhead of using TCP/IP and complex
wrapping code just to communicate some data between two process.
A note on protocol version
u>NB: does not deal with IP (4 or 6) protocol ! .
When using a jsimconnect instance, some constructors accepts a protocol version number. These version indicates
the simconnect protocol to emulate when talking to the remote FSX. The different FSX updates included new features
to the simconnect protocol & client library, but also broke backward compatibility when the simconnect client
is newer than the remote Flight Simulator instance.
JSimconnect uses the version given to the constructor to emulate an older simconnect protocol client,
thus allowing to connect to older FSX versions. Note that by default, the protocol number used is the most up
to date, and consequently a VERSION_MISMATCH exception will be received upon connecting to older FSX version.
As of jsimconnect 0.7, this protocol version is 0x4, corresponding to Pre-SP2/Acceleration XPack.
As of jsimconnect 0.7 the supported protocol numbers are :
- 0x2 (RTM version). Note that 0x1 (possibly from fsx beta) is not supported
- 0x3 (SP1).
- 0x4 (SP2/Acceleration)
When specifying a protocol version to emulate, some functions will be inhibited as they may not be available
in the current version. For instance modeless UI or facilities are not available before SP1.
Constructing a simconnect instance emulating protocol 0x2 will systematically throw an UnsupportedOperationException
exception when calling this methods.