Architecture Overview
A Windows .NET worker app that bridges Microsoft Flight Simulator (via SimConnect) to the Simops backend over HTTP/WebSockets and optional RabbitMQ messaging.
Solution layout
Two projects in SimopsConnect Solution:
SimulatorConnect/: thin wrapper around the SimConnect SDK. Owns the Win32 message loop, manages the SimConnect lifecycle, and exposes typed observables of simulator data.SimopsConnect/: the host app. Layered intoApplication/(domain services) andInfrastructure/(HTTP, WebSocket, messaging).Program.cswires the generic host, WorkerService orchestrates the pipelines.
Runtime composition (Program.cs:19)
- Builds an
IHostwith config from Azure App Configuration +appsettings.json+ filtered command-line args (sensitive keys like JWT/Messaging credentials are stripped from CLI overrides — Program.cs:78). - Registers three layers via DI extension methods:
AddApplication(),AddInfrastructure(),AddSimConnect(). - Starts WorkerService, then runs
MessageWindow.MessageLoop()on the main thread (required for SimConnect's Win32 callbacks), withhost.Run()on a background thread. - Logging via Serilog → console.
Data flow (the core abstraction is Rx)

Infrastructure
- HTTP (Infrastructure/Http/): HttpService listens on Http:Endpoint (default :45928), with RequestsHandlerService dispatching requests; JWT validation configured via Jwt:Issuer/Audience/JwksUri.
AllowImmediateStartbypasses the start handshake. - WebSocket (WebSocketService): broadcasts combined aircraft state + flight info to all connected clients on :45929. Recent commit 0557aa3 added multi-client support.
- Messaging (Infrastructure/Messaging/): RabbitMQ publisher, gated by Messaging:Enabled. Two routing keys: flights (metadata) and flightevents (telemetry tick).
Configuration model
Three options sections bound to strongly-typed configs: HttpConfig, MessagingConfig, DataConfig (the latter holds Aircraft:RefreshInterval). Azure App Config overlays per-environment values; the local appsettings.json is mostly defaults/empty placeholders.
Notable design choices
- Reactive Extensions everywhere — services expose
IObservable/Subjectrather than events or async streams. This keeps the worker pipeline composable (WithLatestFrom,Where,DistinctUntilChanged) and lets the SimConnect callback loop fan out cleanly. - Singleton lifetime for all application services: state (connection, current flight) is held in
BehaviorSubjectsinside the services themselves, no external store. - Hidden Azure App Config endpoint
- Win32 coupling — the app is win-x64 only because SimConnect requires a window handle for its callback model (MessageWindow.MessageLoop()).