Engine/Client Usage
The engine package provides a high-level client for interacting with SimConnect. This document covers the complete API for direct simulator communication.
See also: Configuration Options for all available options when creating a client.
Creating a Client
Using the Root Package
import "github.com/mrlm-net/simconnect"
client := simconnect.NewClient("MyApp")
Using the Engine Package Directly
import "github.com/mrlm-net/simconnect/pkg/engine"
client := engine.New("MyApp")
simconnect.NewClient returns the engine.Client interface; engine.New returns *engine.Engine, which also has the methods outside the interface (the camera API and SetSystemEventState).
Connection Lifecycle
Connect
Establishes a connection to the SimConnect server.
if err := client.Connect(); err != nil {
log.Fatal("Failed to connect:", err)
}
Disconnect
Stops the dispatcher, closes the stream and closes the connection.
defer client.Disconnect()
A client is single-use: after Disconnect (or the simulator quitting) its context is done and its stream closed. To connect again, create a new client (as pkg/manager does).
Stream
Returns a read-only channel for receiving SimConnect messages. The first call starts the dispatcher.
stream := client.Stream()
for msg := range stream {
// Handle incoming messages
}
The channel closes after the simulator’s quit message, when the context is cancelled, or when the connection is lost: then the last message carries an Err wrapping engine.ErrConnectionLost (the pipe closed, or 100 dispatch errors in a row).
Data Definitions
Data definitions describe the structure of data you want to receive from or send to the simulator.
AddToDataDefinition
Adds a variable to a data definition. Call multiple times to build composite definitions.
import "github.com/mrlm-net/simconnect/pkg/types"
// Define aircraft position data
const PositionDefID = 1000
client.AddToDataDefinition(
PositionDefID,
"PLANE LATITUDE",
"degrees",
types.SIMCONNECT_DATATYPE_FLOAT64,
0, // epsilon (change threshold)
0, // datum ID
)
client.AddToDataDefinition(
PositionDefID,
"PLANE LONGITUDE",
"degrees",
types.SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
)
client.AddToDataDefinition(
PositionDefID,
"PLANE ALTITUDE",
"feet",
types.SIMCONNECT_DATATYPE_FLOAT64,
0, 0,
)
ClearDataDefinition
Removes a previously created data definition.
client.ClearDataDefinition(PositionDefID)
RegisterDataset
Registers a pre-built dataset from the datasets package.
import "github.com/mrlm-net/simconnect/pkg/datasets/aircraft"
client.RegisterDataset(PositionDefID, aircraft.NewPositionDataset())
RegisterFacilityDataset
Registers a pre-built facility dataset from the datasets/facilities package. Unlike RegisterDataset which uses AddToDataDefinition, this uses AddToFacilityDefinition internally.
import "github.com/mrlm-net/simconnect/pkg/datasets/facilities"
client.RegisterFacilityDataset(AirportDefID, facilities.NewAirportFacilityDataset())
client.RegisterFacilityDataset(RunwayDefID, facilities.NewRunwayFacilityDataset())
client.RegisterFacilityDataset(ParkingDefID, facilities.NewParkingFacilityDataset())
client.RegisterFacilityDataset(FrequencyDefID, facilities.NewFrequencyFacilityDataset())
Available facility dataset constructors in pkg/datasets/facilities:
| Constructor | Data |
|---|---|
NewAirportFacilityDataset() |
Airport info (name, ICAO, position, tower, transition) |
NewRunwayFacilityDataset() |
Runway dimensions, heading, surface, lighting |
NewParkingFacilityDataset() |
Parking spots, gates, ramps |
NewFrequencyFacilityDataset() |
COM/NAV frequencies |
NewTaxiPointFacilityDataset() |
Taxiway intersection points |
NewTaxiPathFacilityDataset() |
Taxiway paths and routes |
NewTaxiNameFacilityDataset() |
Taxiway names |
NewHelipadFacilityDataset() |
Helipad locations and properties |
NewJetwayFacilityDataset() |
Jetway data |
NewPavementFacilityDataset() |
Runway pavement (length, width) |
NewApproachLightsFacilityDataset() |
Runway approach lights |
NewVASIFacilityDataset() |
Runway VASI |
NewStartFacilityDataset() |
Start positions |
NewDepartureFacilityDataset() |
SID procedures |
NewArrivalFacilityDataset() |
STAR procedures |
NewRunwayTransitionFacilityDataset() |
SID/STAR runway transitions |
NewEnrouteTransitionFacilityDataset() |
SID/STAR enroute transitions |
NewApproachFacilityDataset() |
Approach procedures |
NewApproachTransitionFacilityDataset() |
Approach transitions |
NewApproachLegFacilityDataset() |
Procedure legs (APPROACH_LEG) |
NewFinalApproachLegFacilityDataset() |
Final approach legs |
NewMissedApproachLegFacilityDataset() |
Missed approach legs |
NewVORFacilityDataset() |
VOR navaid data |
NewNDBFacilityDataset() |
NDB navaid data |
NewWaypointFacilityDataset() |
Waypoint data |
NewRouteFacilityDataset() |
Airway segments of a waypoint (ROUTE) |
Requesting Data
RequestDataOnSimObject
Requests data for a specific sim object with optional periodic updates.
const PositionReqID = 1001
// Request once
client.RequestDataOnSimObject(
PositionReqID,
PositionDefID,
types.SIMCONNECT_OBJECT_ID_USER, // User aircraft
types.SIMCONNECT_PERIOD_ONCE, // Single request
types.SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT,
0, 0, 0,
)
// Request every second
client.RequestDataOnSimObject(
PositionReqID,
PositionDefID,
types.SIMCONNECT_OBJECT_ID_USER,
types.SIMCONNECT_PERIOD_SECOND,
types.SIMCONNECT_DATA_REQUEST_FLAG_CHANGED, // Only when changed
0, 0, 0,
)
RequestDataOnSimObjectType
Requests data for all objects of a specific type within a radius.
// Get all aircraft within 50 nautical miles
client.RequestDataOnSimObjectType(
TrafficReqID,
TrafficDefID,
50 * 1852, // Radius in meters (50nm)
types.SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT,
)
SetDataOnSimObject
Sends data to the simulator to modify object state.
type AircraftPosition struct {
Latitude float64
Longitude float64
Altitude float64
}
pos := AircraftPosition{
Latitude: 47.4647,
Longitude: -122.3078,
Altitude: 10000,
}
client.SetDataOnSimObject(
PositionDefID,
types.SIMCONNECT_OBJECT_ID_USER,
types.SIMCONNECT_DATA_SET_FLAG_DEFAULT,
0,
uint32(unsafe.Sizeof(pos)),
unsafe.Pointer(&pos),
)
Processing Messages
Message Structure
The Stream() channel returns Message structs containing the raw SimConnect data.
type Message struct {
*types.SIMCONNECT_RECV // DwSize, DwVersion, DwID (types.DWORD)
Size uint32 // Size of the message
Err error // Set on a dispatch error
// unexported: the pooled buffer
}
On a dispatch error the stream sends a Message with Err set and a nil SIMCONNECT_RECV. Check msg.Err != nil before reading msg.DwID. Release() returns the buffer to the pool.
Casting Message Data
Use CastDataAs to convert raw data to typed structs:
type AircraftPosition struct {
Latitude float64
Longitude float64
Altitude float64
}
for msg := range client.Stream() {
switch types.SIMCONNECT_RECV_ID(msg.DwID) {
case types.SIMCONNECT_RECV_ID_SIMOBJECT_DATA:
data := msg.AsSimObjectData()
if data.DwRequestID == PositionReqID {
pos := engine.CastDataAs[AircraftPosition](&data.DwData)
fmt.Printf("Position: %.4f, %.4f @ %.0fft\n",
pos.Latitude, pos.Longitude, pos.Altitude)
}
}
}
Signature: func CastDataAs[T any](dwData *types.DWORD) *T
The struct layout must exactly match the SimConnect data definition order and types. Use float64 for SIMCONNECT_DATATYPE_FLOAT64, int32/uint32 for INT32, and fixed-size byte arrays for strings ([256]byte for STRING256).
Message Type Methods
The Message struct provides helper methods that cast the raw pointer to a typed struct. Each returns nil when DwID does not match:
| Method | SIMCONNECT_RECV_ID checked |
Return type |
|---|---|---|
AsOpen() |
OPEN |
*types.SIMCONNECT_RECV_OPEN |
AsException() |
EXCEPTION |
*types.SIMCONNECT_RECV_EXCEPTION |
AsEvent() |
EVENT |
*types.SIMCONNECT_RECV_EVENT |
AsEventFrame() |
EVENT_FRAME |
*types.SIMCONNECT_RECV_EVENT_FRAME |
AsEventFilename() |
EVENT_FILENAME |
*types.SIMCONNECT_RECV_EVENT_FILENAME |
AsEventObjectAddRemove() |
EVENT_OBJECT_ADDREMOVE |
*types.SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE |
AsSimObjectData() |
SIMOBJECT_DATA |
*types.SIMCONNECT_RECV_SIMOBJECT_DATA |
AsSimObjectDataBType() |
SIMOBJECT_DATA_BYTYPE |
*types.SIMCONNECT_RECV_SIMOBJECT_DATA_BTYPE |
AsClientData() |
CLIENT_DATA |
*types.SIMCONNECT_RECV_CLIENT_DATA |
AsAssignedObjectID() |
ASSIGNED_OBJECT_ID |
*types.SIMCONNECT_RECV_ASSIGNED_OBJECT_ID |
AsFacilityData() |
FACILITY_DATA |
*types.SIMCONNECT_RECV_FACILITY_DATA |
AsFacilityDataEnd() |
FACILITY_DATA_END |
*types.SIMCONNECT_RECV_FACILITY_DATA_END |
AsFacilityList() |
AIRPORT_LIST, VOR_LIST, NDB_LIST or WAYPOINT_LIST |
*types.SIMCONNECT_RECV_FACILITIES_LIST |
AsAirportList() / AsNDBList() / AsVORList() / AsWaypointList() |
the matching *_LIST |
*types.SIMCONNECT_RECV_AIRPORT_LIST etc. |
AsSimObjectAndLiveryEnumeration() |
ENUMERATE_SIMOBJECT_AND_LIVERY_LIST |
*types.SIMCONNECT_RECV_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST |
AsEnumerateInputEvents() |
ENUMERATE_INPUT_EVENTS |
*types.SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS |
AsGetInputEvent() |
GET_INPUT_EVENT |
*types.SIMCONNECT_RECV_GET_INPUT_EVENT |
AsSubscribeInputEvent() |
SUBSCRIBE_INPUT_EVENT |
*types.SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT |
AsFlowEvent() |
FLOW_EVENT |
*types.SIMCONNECT_RECV_FLOW_EVENT |
AsCommBus() |
COMM_BUS |
*types.SIMCONNECT_RECV_COMM_BUS (data via CommBusData()) |
AsCameraStatus() |
CAMERA_STATUS |
*types.SIMCONNECT_RECV_CAMERA_STATUS |
AsCameraData() |
CAMERA_DATA |
(types.SIMCONNECT_DATA_CAMERA, bool): decoded, false instead of nil |
The list messages (AsAirportList, AsNDBList, AsVORList, AsWaypointList, AsEnumerateInputEvents, AsSimObjectAndLiveryEnumeration) have an Entries() method that returns the entries following the header. The input event, flow event, CommBus and camera helpers are MSFS 2024 only: against MSFS 2020 they always return nil. There is no helper for the quit message (SIMCONNECT_RECV_ID_QUIT); the stream closes after it.
Parsing Strings
SimConnect returns null-terminated strings. Use BytesToString to convert:
title := engine.BytesToString(data.SzTitle[:])
Attributing Exceptions
SimConnect reports failed requests asynchronously as SIMCONNECT_RECV_ID_EXCEPTION messages that carry only the send ID of the packet that failed (DwSendID) and the index of the bad parameter (DwIndex). Record the send ID of each request with GetLastSentPacketID right after making it, then look it up when an exception arrives:
sent := map[uint32]string{}
track := func(desc string, err error) {
if id, idErr := client.GetLastSentPacketID(); idErr == nil {
sent[id] = desc
}
}
track("GEAR_DOWN to AI", client.TransmitClientEvent(objectID, evtGearDown, 0,
types.SIMCONNECT_GROUP_PRIORITY_HIGHEST, types.SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY))
// in the message loop
case types.SIMCONNECT_RECV_ID_EXCEPTION:
e := msg.AsException()
log.Printf("exception %d in %q (parameter %d)", e.DwException, sent[uint32(e.DwSendID)], e.DwIndex)
Call GetLastSentPacketID on the same goroutine immediately after the request; a request sent from another goroutine in between would be reported instead. The method is also available on manager.Manager.
System State
RequestSystemState
Requests simulator system state information.
client.RequestSystemState(
StateReqID,
types.SIMCONNECT_SYSTEM_STATE_SIM, // Simulation running state
)
Response arrives as SIMCONNECT_RECV_ID_SYSTEM_STATE message.
Events
SubscribeToSystemEvent
Subscribes to simulator system events.
const PauseEventID = 2000
client.SubscribeToSystemEvent(PauseEventID, "Pause")
client.SubscribeToSystemEvent(2001, "Sim")
client.SubscribeToSystemEvent(2002, "SimStart")
client.SubscribeToSystemEvent(2003, "SimStop")
UnsubscribeFromSystemEvent
Removes a system event subscription.
client.UnsubscribeFromSystemEvent(PauseEventID)
MapClientEventToSimEvent
Maps a client event ID to a simulator event name.
const GearToggleEventID = 3000
client.MapClientEventToSimEvent(GearToggleEventID, "GEAR_TOGGLE")
TransmitClientEvent
Sends an event to the simulator.
// Toggle landing gear
client.TransmitClientEvent(
types.SIMCONNECT_OBJECT_ID_USER,
GearToggleEventID,
0, // Event data
types.SIMCONNECT_GROUP_PRIORITY_HIGHEST,
types.SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY,
)
TransmitClientEventEx1
Extended version with additional data parameters.
client.TransmitClientEventEx1(
types.SIMCONNECT_OBJECT_ID_USER,
eventID,
types.SIMCONNECT_GROUP_PRIORITY_HIGHEST,
types.SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY,
[5]uint32{data0, data1, data2, data3, data4},
)
Notification Groups
AddClientEventToNotificationGroup
Groups events for priority-based handling.
const FlightControlsGroup = 4000
client.AddClientEventToNotificationGroup(
FlightControlsGroup,
GearToggleEventID,
false, // maskable
)
SetNotificationGroupPriority
Sets the priority for a notification group.
client.SetNotificationGroupPriority(
FlightControlsGroup,
types.SIMCONNECT_GROUP_PRIORITY_HIGHEST,
)
ClearNotificationGroup
Removes all events from a notification group.
client.ClearNotificationGroup(FlightControlsGroup)
AI Traffic
A guide with the kinds, IDs and lifecycle: Engine AI Objects.
AICreateParkedATCAircraft
Creates an AI aircraft parked at an airport.
client.AICreateParkedATCAircraft(
"Airbus A320 Neo Asobo",
"N12345",
"KSEA", // ICAO code
CreateReqID,
)
AICreateEnrouteATCAircraft
Creates an AI aircraft following a flight plan.
client.AICreateEnrouteATCAircraft(
"Boeing 747-8 Asobo",
"UAL123",
0, // Flight number
"KSEA_KLAX.pln", // Flight plan file
0.5, // Progress (0.0-1.0)
false, // Touch-and-go
CreateReqID,
)
AISetAircraftFlightPlan
Assigns a flight plan to an existing AI aircraft.
client.AISetAircraftFlightPlan(
objectID,
"KSEA_KLAX.pln",
FlightPlanReqID,
)
AIRemoveObject
Removes an AI object from the simulation.
client.AIRemoveObject(objectID, RemoveReqID)
AIReleaseControl
Releases control of an AI object back to the simulator.
client.AIReleaseControl(objectID, ReleaseReqID)
AICreateNonATCAircraft
Creates a non-ATC-controlled aircraft at a specific position.
initPos := types.SIMCONNECT_DATA_INITPOSITION{
Latitude: 47.4502,
Longitude: -122.3088,
Altitude: 5000,
Pitch: 0,
Bank: 0,
Heading: 270,
OnGround: 0,
Airspeed: 120,
}
client.AICreateNonATCAircraft("Cessna Skyhawk Asobo", "N12345", initPos, CreateReqID)
AICreateSimulatedObject
Creates a non-aircraft simulated object (ground vehicle, boat, etc.).
client.AICreateSimulatedObject("Generic Ground Vehicle", initPos, CreateReqID)
EX1 Variants (Livery Selection)
The EX1 variants of AI creation methods add a livery parameter:
client.AICreateParkedATCAircraftEX1("Boeing 787-10 Asobo", "House", "N12345", "KSEA", ReqID)
client.AICreateEnrouteATCAircraftEX1("Airbus A320 Neo Asobo", "Asobo", "UAL123", 0, "plan.pln", 0.5, false, ReqID)
client.AICreateNonATCAircraftEX1("Cessna Skyhawk Asobo", "Blue", "N12345", initPos, ReqID)
EnumerateSimObjectsAndLiveries
Lists the installed models of an object type (SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, HELICOPTER, BOAT, GROUND, ALL, USER) and their liveries, for traffic injection or aircraft pickers.
client.EnumerateSimObjectsAndLiveries(EnumReqID, types.SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT)
// in the message loop
if recv := msg.AsSimObjectAndLiveryEnumeration(); recv != nil && recv.DwRequestID == EnumReqID {
for _, item := range recv.Entries() {
title := engine.BytesToString(item.AircraftTitle[:]) // aircraft.cfg title
livery := engine.BytesToString(item.LiveryName[:]) // empty without separate liveries
fmt.Printf("%-60s %s\n", title, livery)
}
if recv.DwEntryNumber+recv.DwArraySize >= recv.DwOutOf {
// last batch
}
}
Replies come in batches (SIMCONNECT_RECV_ID_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST): DwArraySize entries from DwEntryNumber, DwOutOf in all. Entries() reads the [256]byte AircraftTitle / LiveryName pairs in place after the 28-byte header.
Facilities
RequestFacilitiesList
Requests a list of facilities (airports, waypoints, etc.).
client.RequestFacilitiesList(
FacilitiesReqID,
types.SIMCONNECT_FACILITY_LIST_AIRPORT,
)
RequestFacilityData
Requests detailed data for a specific facility.
client.RequestFacilityData(
FacilityDefID,
FacilityDataReqID,
"KSEA",
"", // Region (optional)
)
RequestFacilityDataEX1
Extended version that explicitly specifies the facility type.
client.RequestFacilityDataEX1(
FacilityDefID,
FacilityDataReqID,
"KSEA",
"", // Region (optional)
byte(types.SIMCONNECT_FACILITY_DATA_AIRPORT), // Explicit facility type
)
RequestJetwayData
Requests jetway data for a specific airport.
indexes := []int32{0, 1, 2}
client.RequestJetwayData("KSEA", uint32(len(indexes)), &indexes[0])
RequestAllFacilities
Requests all facilities of a specific type.
client.RequestAllFacilities(
types.SIMCONNECT_FACILITY_LIST_AIRPORT,
AllFacilitiesReqID,
)
SubscribeToFacilitiesEX1
Extended subscription with separate request IDs for facilities entering and leaving range.
client.SubscribeToFacilitiesEX1(
types.SIMCONNECT_FACILITY_LIST_AIRPORT,
NewInRangeReqID,
OldOutRangeReqID,
)
AddFacilityDataDefinitionFilter
Filters facility data requests.
client.AddFacilityDataDefinitionFilter(
FacilityDefID,
"filterPath",
filterDataPtr,
filterDataSize,
)
ClearAllFacilityDataDefinitionFilters
Removes all filters from a facility definition.
client.ClearAllFacilityDataDefinitionFilters(FacilityDefID)
SubscribeToFacilities
Subscribes to facility updates within a radius.
client.SubscribeToFacilities(
types.SIMCONNECT_FACILITY_LIST_AIRPORT,
FacilitySubReqID,
)
AddToFacilityDefinition
Defines the data fields to receive for facilities.
client.AddToFacilityDefinition(FacilityDefID, "OPEN AIRPORT")
client.AddToFacilityDefinition(FacilityDefID, "NAME")
client.AddToFacilityDefinition(FacilityDefID, "LATITUDE")
client.AddToFacilityDefinition(FacilityDefID, "LONGITUDE")
Flight Operations
FlightLoad
Loads a saved flight file.
client.FlightLoad("C:/Users/Pilot/Flights/MyFlight.flt")
FlightPlanLoad
Loads a flight plan file.
client.FlightPlanLoad("C:/Users/Pilot/FlightPlans/KSEA_KLAX.pln")
FlightSave
Saves the current flight state.
client.FlightSave(
"C:/Users/Pilot/Flights/SavedFlight.flt",
"My Saved Flight",
"Saved at KSEA runway 16L",
)
Other Client APIs
Not covered above:
SetSystemEventState,RequestNotificationGroup,RemoveClientEvent,RequestFacilitiesListEX1,UnsubscribeToFacilitiesEX1— thin wrappers of the SimConnect functions of the same name.SubscribeToFlowEvent/UnsubscribeFromFlowEvent— flow events (MSFS 2024), read withmsg.AsFlowEvent().engine.SystemStateFloat64(recv)— the float value of aSIMCONNECT_RECV_SYSTEM_STATEreply.engine.PackWaypoints(wps)andengine.WaypointWireSize— packSIMCONNECT_DATA_WAYPOINTslices forSetDataOnSimObject.- Client data areas (
MapClientDataNameToID,CreateClientData,AddToClientDataDefinition,RequestClientData,SetClientData,ClearClientDataDefinition, all on theengine.Clientinterface): Client Data Areas. Input events (MSFS 2024): Input Events. Camera (MSFS 2024,*engine.Engineonly): Camera.
Example: Complete Data Loop
package main
import (
"fmt"
"os"
"os/signal"
"github.com/mrlm-net/simconnect/pkg/engine"
"github.com/mrlm-net/simconnect/pkg/types"
)
type AircraftData struct {
Latitude float64
Longitude float64
Altitude float64
Heading float64
}
const (
DataDefID = 1000
DataReqID = 1001
)
func main() {
client := engine.New("DataLoop")
if err := client.Connect(); err != nil {
panic(err)
}
defer client.Disconnect()
// Define data structure
client.AddToDataDefinition(DataDefID, "PLANE LATITUDE", "degrees", types.SIMCONNECT_DATATYPE_FLOAT64, 0, 0)
client.AddToDataDefinition(DataDefID, "PLANE LONGITUDE", "degrees", types.SIMCONNECT_DATATYPE_FLOAT64, 0, 0)
client.AddToDataDefinition(DataDefID, "PLANE ALTITUDE", "feet", types.SIMCONNECT_DATATYPE_FLOAT64, 0, 0)
client.AddToDataDefinition(DataDefID, "PLANE HEADING DEGREES TRUE", "degrees", types.SIMCONNECT_DATATYPE_FLOAT64, 0, 0)
// Request periodic updates
client.RequestDataOnSimObject(
DataReqID, DataDefID,
types.SIMCONNECT_OBJECT_ID_USER,
types.SIMCONNECT_PERIOD_SECOND,
types.SIMCONNECT_DATA_REQUEST_FLAG_CHANGED,
0, 0, 0,
)
// Handle shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
stream := client.Stream()
for {
select {
case <-sigChan:
fmt.Println("Shutting down...")
return
case msg, ok := <-stream:
if !ok {
return
}
if msg.Err != nil {
fmt.Println("stream error:", msg.Err)
continue
}
if types.SIMCONNECT_RECV_ID(msg.DwID) == types.SIMCONNECT_RECV_ID_SIMOBJECT_DATA {
data := msg.AsSimObjectData()
if data.DwRequestID == DataReqID {
aircraft := engine.CastDataAs[AircraftData](&data.DwData)
fmt.Printf("Pos: %.4f, %.4f | Alt: %.0fft | Hdg: %.1f°\n",
aircraft.Latitude, aircraft.Longitude,
aircraft.Altitude, aircraft.Heading)
}
}
}
}
}
See Also
- Client Configuration — All configuration options
- Manager Usage — Automatic connection lifecycle management
- Examples — Working code samples
CommBus (MSFS 2024)
CommBus passes events with string data (usually JSON) between SimConnect clients, WebAssembly modules and JavaScript gauges or panels: an in-sim add-on can answer an app this way (#678).
client.SubscribeToCommBusEvent(4242, "myaddon.reply")
client.CallCommBusEvent("myaddon.request", types.SIMCONNECT_COMM_BUS_BROADCAST_TO_DEFAULT, `{"icao":"LKPR"}`)
var parts engine.CommBusAssembler
for msg := range client.Stream() {
if id, data, ok := parts.Add(&msg); ok {
fmt.Println(id, data) // 4242 {"metar":"..."}
}
}
SIMCONNECT_COMM_BUS_BROADCAST_TO_* says who a call reaches: JS, WASM, SIMCONNECT (other clients), SIMCONNECT_SELF_CALL (with SIMCONNECT, the caller too); DEFAULT is the first three. A subscribed event arrives as SIMCONNECT_RECV_ID_COMM_BUS (Message.AsCommBus, CommBusData); data too long for one message comes in parts, which CommBusAssembler joins. Checked live with a self call: 16 bytes and 9 KB, each back intact in one message.