4 KiB
Handoff — PON Go iOS
Context for the next session/developer. Pairs with README.md and
MCMS_API.md.
Status
Feature-complete and (per off-device typecheck + the user's Xcode builds) compiling. Screens: Login, Settings, Dashboard (counts, total OLT traffic, Health with tappable drill-downs, ONU-state breakdown, detailed-stats + auto-refresh toggles), ONU list + detail (Overview with status/firmware+update/ optical-FEC/UNI/traffic, CPE DHCP, Config raw-JSON tree, Alarms, Logs; reset + firmware behind hardened confirms), OLT list + detail (status/uptime/traffic/ environment/uplink/registration buckets, reset).
Architecture
AppEnvironment(@MainActor @Observable) owns the activeMCMSConnection, persists the non-secretAPIConfigurationto UserDefaults, keeps credentials in the Keychain, and routesRootView(Settings → Login → mainTabView).- Networking core:
APIConfiguration→SessionStore/APIClient→ repositories. Mongo documents are kept as a dynamicJSONValue(APIEnvelope.swift) and read via typed accessors onMongoDocumentstructs (DeviceModels.swift) — type the fields you use, leave the rest raw. - View models are
@MainActor @Observableclasses with aLoadPhase+load().
API gotchas (handled in code — don't regress)
- Single-encode URLs.
APIClient.makeRequestbuilds the path withURLComponents.path(encodes once, keeps:in MAC ids raw);MCMSEndpointkeeps ids RAW.appendingPathComponentdouble-encoded MAC colons → MCMS "invalid id". (Verified empirically.) - 401 bounces to login; 403 does NOT —
APIError.requiresReauthenticationis 401-only (403 is permission/CSRF; re-login won't help). TheonAuthExpiredhook flowsAPIClient → MCMSConnection → AppEnvironment. - Writes return
{"status":"success"}with nodata—decodeEnvelopereturns the type's empty value instead of throwing (so login + all writes work). - ONU registration is on OLT-STATE buckets (
OLTRepository.registrationMap), not ONU-STATE. Parent OLT isOLT.MAC Address. Friendly names areONU.Name/OLT.Name(NOTNetconf.Name/NETCONF.Name, which default to the id), fetched viaprojection. - CPE DHCP = web helper
GET /api/cpe/onu/<id>/(versionless, bare[code, cpe…]array —APIClient.getRaw). - Firmware = Procedure 7 (
FirmwareUpgrade.apply, unit-tested against a real config): GET ONU-CFG → write filename/version into the inactive bank → full- doc PUT. Inactive-bank only; still test on a spare ONU before production. - Timestamps are UTC
yyyy-MM-dd HH:mm:ss[.SSSSSS]with a literal space (MongoTimestamp, not ISO8601). Uptime = stateTime−Online Time. - Everything is
/api/v1except/v3/tasks/configs/(unused). Cookies may be__Host--prefixed (SessionStorematches either)./apiis auto-appended to the base URL in Settings.
Known real-world notes
- One lab box (
mcms.lab.svorka.net) once sent an illegalUpgrade: h2header over HTTP/2 that iOS rejects (-1005). Fix is server-side (ApacheProtocols http/1.1) or an HTTP/1.1 reverse proxy; iOS has no supported "force HTTP/1.1". - The base URL must include
/api; Settings normalises this.
Verify loop
swiftc -typecheck against the macOS SDK for the core + view models (see README).
Tricky SwiftUI bits: compile isolated snippets sans iOS-only modifiers. No iOS SDK
on the dev machine, so full builds are the user's Xcode step.
Repo split
Recommended: consolidate the flat sources + Assets.xcassets into the Xcode
project and git-init that as the iOS repo (with docs/MCMS_API.md + the PDFs).
The included .gitignore covers Xcode/Swift build artifacts. The Android app is a
separate repo (../mcms_android), self-contained.
Possible next steps
OLT bulk firmware (Procedure 8 task); Swift Charts for PM history; live optical on the list rows; richer alarm handling; widen test coverage of the firmware PUT against more ONU-CFG shapes.