Migration
Diese Seite wurde aus der AirSimTech MediaWiki migriert.
Startup and Actor Initialization
Overview
When the FMGC application starts, frmMain_Load executes a 9-step boot sequence: loading INI configuration, verifying database connectivity, registering encoding support, configuring the INET client module ID, creating the Akka.NET actor system, wiring the BITE diagnostic target, building the diagnostics menu, resolving actor references, and starting BroadcastRCV server discovery. The actor system creates all 12 actors inside FmgcSupervisor.PreStart and wires their inter-actor references via typed messages — but database preloading is deferred until after the INET connection to ASTServer is established. This ensures that the startup progress pages (SEQ 1-6) are visible on the MCDU display as databases load. The post-connection initialization chain is: INetClient1.Connected → InetConnected → StartPreload → SEQ 1-4 → PreloadComplete → SEQ 5-6 → auto-navigate to STATUS.
Startup Sequence
Step Details
| Step | Method / Call | Notes |
|---|---|---|
| 1 | NLog auto-config | NLog.config in project root; rolling file + console targets |
| 2 | IniConfiguration.Load(iniPath) |
iniPath = Application.StartupPath & "\FMGC.ini"; custom INI parser with case-insensitive lookup |
| 3 | TestPerfDbConnection() |
Opens and immediately closes FMGCPERF1.MDB; logs warning if not found (non-fatal) |
| 4 | System.Text.Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) |
Required before any ARINC 429 encoding; must precede INetActor startup |
| 5 | INetClient1.SetModuleID(55, "FMGC") |
Module ID 55 is the FMGC identity on the INET register bus; must be called before Init |
| 6 | ActorSystem.Create("FMGC") + ActorOf(FmgcSupervisor) |
Props.Create lambda passes frmMain and _config to FmgcSupervisor constructor |
| 6b | BiteNLogTarget registered |
Added to NLog configuration at runtime; routes Warn/Error/Fatal to frmBITE via NLog.LogManager.ReconfigExistingLoggers() |
| 6c | BuildDiagnosticsMenu() |
Creates a MenuStrip with Diagnostics > Side View / Map View / BITE entries |
| 7 | ActorSelection("/user/FmgcSupervisor/INetActor").ResolveOne(TimeSpan.FromSeconds(5)) |
Synchronous .Result; 5-second timeout; INetActor is created early in PreStart so resolution is near-instant. Note: FlightPlanActor refs are resolved lazily on first diagnostic button use (not at startup) because PreStart blocks during synchronous OPCAMI DB read — actors created after that point don't exist yet when frmMain_Load runs. |
FmgcSupervisor.PreStart Wiring
FmgcSupervisor.PreStart creates all 13 actors then sends wiring messages to establish inter-actor references. All wiring is complete before the first KernelTick fires (the tick timer starts at TimeSpan.Zero initial delay, but actor mailboxes process in order, so wiring messages arrive before external messages). Note: NavDbActor is created but does not preload databases in PreStart — preloading is deferred until StartPreload is received after the INET connection is established (see Post-Connection Initialization Chain).
Actor Creation Order
| # | Actor | Path | Created via |
|---|---|---|---|
| 1 | KernelActor | /user/FmgcSupervisor/KernelActor |
Context.ActorOf(Of KernelActor)("KernelActor") |
| 2 | TrajectoryActor | /user/FmgcSupervisor/TrajectoryActor |
Context.ActorOf(Of Trajectory.TrajectoryActor)("TrajectoryActor") |
| 3 | McduCaptainActor | /user/FmgcSupervisor/McduCaptainActor |
Context.ActorOf(Props.Create(Of Mcdu.McduActor)(McduSide.Captain), "McduCaptainActor") |
| 4 | McduFoActor | /user/FmgcSupervisor/McduFoActor |
Context.ActorOf(Props.Create(Of Mcdu.McduActor)(McduSide.FirstOfficer), "McduFoActor") |
| 5 | GuidanceActor | /user/FmgcSupervisor/GuidanceActor |
Context.ActorOf(Of Guidance.GuidanceActor)("GuidanceActor") |
| 6 | INetActor | /user/FmgcSupervisor/INetActor |
Context.ActorOf(Of Inet.INetActor)("INetActor") |
| 7 | NavDbActor | /user/FmgcSupervisor/NavDbActor |
Props.Create(Of NavDb.NavDbActor)(astnavPath, userdataPath) |
| 8 | PrimaryFlightPlanActor | /user/FmgcSupervisor/PrimaryFlightPlanActor |
Props.Create(Of FlightPlan.FlightPlanActor)("PrimaryPlan") |
| 9 | SecondaryFlightPlanActor | /user/FmgcSupervisor/SecondaryFlightPlanActor |
Props.Create(Of FlightPlan.FlightPlanActor)("SecondaryPlan") |
| 10 | AcarsActor | /user/FmgcSupervisor/AcarsActor |
Props.Create(Of Acars.AcarsActor)(acarsDbPath, metarPath, inetActor) |
| 11 | UserdataActor | /user/FmgcSupervisor/UserdataActor |
Props.Create(Of Userdata.UserdataActor)(userdataPath) |
| 12 | SimBriefActor | /user/FmgcSupervisor/SimBriefActor |
Context.ActorOf(Of SimBrief.SimBriefActor)("SimBriefActor") |
| 13 | TmpyActor | /user/FmgcSupervisor/TmpyActor |
Context.ActorOf(Of Mcdu.TmpyActor)("TmpyActor") |
Post-Connection Initialization Chain
Database preloading and startup page display are deferred until after INetClient1 connects to ASTServer. This ensures the MCDU display is live and can render the startup progress pages as each database loads. Without this ordering, SEQ 1-6 messages would be published before the INET transport is active and the startup pages would never be visible.
Message Chain
| # | Event / Message | From | To | What Happens |
|---|---|---|---|---|
| 1 | INetClient1.Connected |
ASTServer | frmMain | INET connection established; frmMain tells FmgcSupervisor |
| 2 | InetConnected |
frmMain | FmgcSupervisor | FmgcSupervisor sends StartPreload to NavDbActor |
| 3 | StartPreload |
FmgcSupervisor | NavDbActor | NavDbActor begins preloading databases |
| 4 | StartupProgress(1) |
NavDbActor | EventStream | Airports loading — McduActors render START-UP page |
| 5 | StartupProgress(2) |
NavDbActor | EventStream | Navaids loading |
| 6 | StartupProgress(3) |
NavDbActor | EventStream | Waypoints loading |
| 7 | StartupProgress(4) |
NavDbActor | EventStream | User waypoints loading |
| 8 | PreloadComplete (with AiracInfo) |
NavDbActor | FmgcSupervisor | All databases loaded; carries AIRAC cycle data; FmgcSupervisor sends CallCreateRoute("8999") to INetActor (first subscribe — VB6 line 4067) |
| 9 | Register 8999 (first) | ASTServer | FmgcSupervisor (via EventStream) | Routing-complete signal received; FmgcSupervisor publishes SEQ 5, sends DataTX 2281=1 and 2607=0, then fires ~97 bulk CallCreateRoutes in exact VB6 order (lines 5165-5293) with "8999" as the last route |
| 10 | StartupProgress(5) |
FmgcSupervisor | EventStream | SERVER DATA receiving — McduActors render startup progress. MCDU keypresses are discarded while on Startup page. |
| 11 | Register 8999 (second) | ASTServer | FmgcSupervisor (via EventStream) | All register subscriptions confirmed routed; FmgcSupervisor publishes SEQ 6, merges OPCAMI + AIRAC into complete StatusSnapshot, sends SetStatusData to both McduActors |
| 12 | StartupProgress(6) |
FmgcSupervisor | EventStream | Startup complete |
| 13 | Auto-navigate | McduActor | — | Both MCDUs switch from START-UP to STATUS page |
Key Design Decisions
- NavDbActor.PreStart does NOT preload. Unlike earlier implementations where
PreStartcalledPreloadAll()synchronously, the actor now waits for aStartPreloadmessage. This decouples actor creation from database I/O and allows the INET connection to be established first. - frmMain is the bridge. The
INetClient1.ConnectedCOM event fires on the UI thread. frmMain forwards it as a Tell to the actor system, bridging COM events into the Akka message flow. - McduActor guards keys during startup. While
_activePage = Startup, all keystroke/scratchpad/CLR events are discarded (with keystroke ack still sent to prevent external MCDU freeze). Keypresses are only processed after auto-navigation to STATUS. - SEQ 5→6 is gated on register 8999. FmgcSupervisor subscribes to
RegisterReceivedon EventStream and filters for register 8999. The first 8999 triggers SEQ 5 and the bulk CreateRoute sequence; the second 8999 triggers SEQ 6. ASTServer sends registers in CreateRoute order, so receiving 8999 (requested last) proves all other registers have been routed. This replaces the earlier 1.5s timer delay.
OPCAMI Configuration Loading
FmgcSupervisor loads the OPCAMI configuration database during PreStart(). This provides aircraft-specific parameters (type, engine, performance thresholds, weight limits, speed limits, fuel settings). The SetStatusData message sends real values to both McduActors, replacing hardcoded defaults.
OpcamiData.ReadFromDatabase() opens OPCAMI.mdb via OleDb, reads all rows from the OPCAMI table, and maps ID-keyed values to 24 typed fields matching the VB6 OPCAMI_Type struct exactly (including /10 division for weight and factor fields). See Navigation Database Access — OPCAMI Configuration Database for the full field table.
Note: SetStatusData is sent twice — first during PreStart with OPCAMI-only data (acType, engType, idleFactor, perfFactor), then again when the second 8999 is received (inside the RegisterReceived handler) with the complete OPCAMI + AIRAC snapshot (adding activeDb, activeDbName, secondDb, secondDbName, databaseUpdateAvailable). The second message overwrites the first in each McduActor's _statusData field. See Navigation Database Access — AIRAC Cycle Information for the AIRAC data flow.
KernelActor.PreStart
KernelActor.PreStart is called by the Akka.NET framework immediately after the actor is created, before any messages are processed.
Key behaviours:
- The timer key
"kernel-tick"ensures that ifPreStartis called again after an actor restart, the previous timer is cancelled and replaced. No duplicate ticks. TimeSpan.Zeroinitial delay means the firstKernelTickfires immediately — the computation cycle begins as soon as the actor is alive.TrajectoryResultsubscription enables KernelActor to cache the latest trajectory for inclusion inGuidanceInputon the next tick.RegisterReceivedsubscription enables KernelActor to maintain the 18-field INET register cache (_cachedLatitude,_cachedLongitude, etc.) used to assembleAircraftState.
Supervision Strategy
FmgcSupervisor uses a OneForOneStrategy with Directive.Restart:
Protected Overrides Function SupervisorStrategy() As SupervisorStrategy
Return New OneForOneStrategy(
Function(ex)
_Logger.Error(ex, "Actor failure — restarting: {0}", ex.Message)
Return Directive.Restart
End Function)
End Function
OneForOne means: if TrajectoryActor crashes, only TrajectoryActor restarts. All 11 other actors continue running without interruption. The Restart directive calls PostStop on the failed actor, creates a fresh instance, and calls PreStart — restoring the timer and EventStream subscriptions automatically.
Source Files
A320_FMGC/frmMain.vb—frmMain_Load9-step boot sequenceA320_FMGC/Kernel/FmgcSupervisor.vb—PreStartactor creation and wiring,SupervisorStrategyA320_FMGC/Kernel/KernelActor.vb—PreStarttimer and EventStream subscriptionsA320_FMGC/Common/IniConfiguration.vb— INI file configuration loaderA320_FMGC/Common/OpcamiData.vb— OPCAMI configuration class; loaded duringFmgcSupervisor.PreStartA320_FMGC/Forms/frmBITE.vb— BITE diagnostics form;BiteNLogTargetregistered at startup