Flight lifecycle (README §4-§7): - Start, resume, finish, cancel and abandon sessions; destructive actions confirm first - Telemetry recorded at 1 Hz to a per-session disk queue (fsync before queued, removed only after the server acks), batched uploads with 5/10/20/40/60 s backoff, Retry-After, and no retry on 4xx; server score and phase shown live - Pre-flight checklist: X-Plane live, position, aircraft type, departure radius, on ground, flight level, route, runways; SimBrief OFP import - App Nap and idle sleep held off while recording; resume after quit or crash X-Plane: - Unconnected loopback UDP (X-Plane replies from its send port) - Finds X-Plane's receive port from its BECN beacon or X-Plane.prf; manual override - Aircraft identity via string datarefs; token-based aircraft type check - Datarefs verified against X-Plane 12.4.3; NaN/inf dropped; ground-speed multiplier counted in simRate; engines 3-4; transponder clamped to 0-5 FlyWithLua (optional second feed): - Settings tab installs a generated Sigantara_ACARS.lua that writes the same datarefs to Output/sigantara_acars_feed.json each second; verified live Also: local diagnostic log with consented upload, release script for Developer ID signing and notarization, two adversarial review rounds applied, 92 tests against a stub server and a fake X-Plane (never production). Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sigantara ACARS — macOS
SwiftUI client for the Sigantara ACARS API. Contract: docs/acars-macos/README.md and openapi.yaml (v0.8.31).
Requirements: Xcode 27+, macOS 14+. No third-party dependencies.
open SigantaraAcars.xcodeproj
xcodebuild test -project SigantaraAcars.xcodeproj -scheme SigantaraAcars -destination 'platform=macOS'
Layout (MVVM)
| Folder | Contents |
|---|---|
SigantaraAcars/Models |
Codable mirror of the OpenAPI schemas |
SigantaraAcars/Services |
APIClient (+ retry rules, request log), Keychain, DeepLink, XPlane (RREF/DREF codec, conversions), XPlaneLink (live UDP link), AircraftCheck, FlightStore (disk queue), AppLog |
SigantaraAcars/ViewModels |
AppModel (auth, deep links), DashboardModel (bid, weather, news, logbook), FlightModel (session lifecycle, recording, upload), Preflight (start checklist) |
SigantaraAcars/Views |
SwiftUI screens; Theme holds the sigantara.com tokens |
Config/Info.plist |
sigantara-acars:// URL scheme (merged with generated plist) |
scripts/release.sh |
Developer ID sign, notarize, staple, zip |
The project uses synchronized folders: new files dropped into SigantaraAcars/ or SigantaraAcarsTests/ are picked up without editing the project.
Flying with it
- Start X-Plane 11 or 12 and load the booked aircraft at the departure gate. ACARS connects by itself; nothing to set up in either app (see Finding X-Plane).
- Flight → Pre-flight: optionally Import from SimBrief (set your SimBrief Pilot ID in Settings), check the cruise level and route, and wait for every check to be green: X-Plane live, position received, aircraft type matches the booking, within the server's departure radius, on the ground.
- Start flight. ACARS records one sample per second to disk and uploads batches of about 15. The server's phase and score show in the flight card; uploads retry with 5/10/20/40/60 s backoff when offline, and nothing is lost on a force-quit.
- After landing and parking: Finish flight. ACARS uploads everything queued, then files the PIREP. If the server refuses (for example "landing not detected"), the flight keeps recording.
- Cancel flight and Abandon (for a session still open on the server) ask first: both are destructive.
Finding X-Plane
X-Plane's receive port is a user setting (49000 by default; it can be anything). ACARS never assumes it:
- Beacon: X-Plane multicasts a
BECNpacket about once a second (239.255.1.1:49707) carrying its receive port. ACARS follows it, from this Mac only. macOS asks once for Local Network access. - Preferences: before a beacon arrives, or if that access is denied, ACARS reads
_rcv_portfrom the running X-Plane'sOutput/preferences/X-Plane.prf(and notices_disable_incoming_networking). - Manual port in Settings, for setups with the beacon turned off.
Data requests and replies use loopback only. X-Plane replies from its send port, so the socket is unconnected on purpose.
Optional: FlyWithLua feed
With FlyWithLua NG+ installed in X-Plane, Settings → FlyWithLua → Install ACARS Script writes Sigantara_ACARS.lua into X-Plane/Resources/plugins/FlyWithLua/Scripts/. Then choose Plugins → FlyWithLua → Reload all Lua script files in X-Plane. The script binds the same datarefs as UDP (it's generated from XPlane.DataRef), writes them once a second to X-Plane/Output/sigantara_acars_feed.json (temp file + rename), and removes the file when Lua stops. ACARS uses whichever feed is fresh and prefers FlyWithLua; the Simulator card says which one is in use. UDP needs nothing installed and stays the default.
Aircraft type check
X-Plane's acf_ICAO and acf_ui_name are compared with the booking's aircraft (and expectedAircraftTitle when the server sends it) as token lists, runs of letters and digits ("Boeing 737-800" is BOEING · 737 · 800), one appearing whole inside the other. A known ICAO designator decides first via a table of the model names bookings use, and the code itself only counts on an exact match. Variants pass (A320neo for A320, 777-300ER for 777-300); different types block the start (737 MAX for 737-800, 737-700 for B737-800, A330-900 for A330-300). If X-Plane reports neither string, the check only warns. Registration is shown but not enforced.
Releasing
TEAM_ID=ABCDE12345 NOTARY_PROFILE=sigantara scripts/release.sh
Archives with Hardened Runtime, signs with Developer ID, notarizes, staples and checks Gatekeeper. Needs your Developer ID certificate and a notarytool keychain profile. An auto-updater is not included: the server has no macOS update manifest yet (README §11).
Notes
- Tests use fixtures, a stub server (URLProtocol) and a fake X-Plane on loopback only. Never point automated tests at the production API.
-demolaunch argument (Debug): sample data, no network, starting flights disabled.-snapshot <file.png>renders the window for review.- Datarefs in
XPlane.DataRefare verified against X-Plane 12.4.3DataRefs.txtand a live sim, but not yet against WindowsXPlaneSimulator.cs. - Nil optional telemetry fields are omitted from JSON rather than sent as
null(fine for Laravelnullablerules). docs/acars-macos/check_contract.pyruns only inside the server monorepo (it reads the PHP routes andModels.cs).- Debug builds are ad-hoc signed; Release enables Hardened Runtime.
- The DREF landing-light write (README §8) exists in the codec only (
XPlane.setLandingLights) and is never sent: what triggers it in the Windows client (XPlaneSimulator.cs/MainForm.cs) isn't available here.