PONGo_android/HANDOFF.md
2026-05-31 14:09:00 +02:00

92 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Handoff — PON Go Android
Context for the next session/developer. Pairs with [`README.md`](README.md) and
[`docs/MCMS_API.md`](docs/MCMS_API.md).
## Architecture
- **`core/`** — pure Kotlin, no Android UI deps. Mirrors the iOS networking core.
- JSON: MCMS docs are heterogeneous Mongo documents, so we keep raw
`kotlinx.serialization` `JsonElement` trees and read fields via the accessors
in `Json.kt` (`el["key"]`, `.string/.int/.double/.array/.obj`) — the analogue
of the iOS `JSONValue`. Models (`Models.kt`) are thin wrappers over a
`JsonElement` with computed properties.
- `ApiClient` (OkHttp): builds versioned requests, injects `Referer` +
`X-CSRFToken` (writes), unwraps the `{status,data}` envelope, maps status
codes to `ApiError`, paginates via the `next` cursor. `Call.await()` bridges
OkHttp to coroutines with cancellation.
- Repositories return model wrappers; `McmsConnection` wires it all; auth/cookies
in `Networking.kt` (`SessionCookieJar` + `SessionStore`), TLS policy in
`ServerTrust`, secrets in `KeychainStore` (EncryptedSharedPreferences).
- **`ui/`** — Jetpack Compose. Navigation is **state-based** in `MainActivity`
(a `List<Screen>` back stack + `BackHandler`), not Navigation-Compose — so
detail screens and the dashboard drill-downs can take in-memory objects
directly. Each screen has a plain **state-holder class** (`…Model`) exposing
`mutableStateOf` fields + `suspend load()/refresh()` — the analogue of the iOS
`@Observable` view models. No androidx `ViewModel`/DI.
## Build / verify loop (this matters)
The dev machine had **no `kotlinc`/`gradle` on PATH**, but Android Studio provides
everything. Two loops:
- **Full build (authoritative):**
```
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
./gradlew :app:assembleDebug --no-daemon --console=plain
```
Needs `local.properties` (`sdk.dir=…`, git-ignored). First run downloads deps
to `~/.gradle`; afterwards it's ~2060 s. This is what proves the whole app
(UI + resources + manifest + icons) compiles.
- **Quick core-only check (no Gradle), when iterating on `core/`:** the bundled
compiler at `…/Android Studio.app/Contents/plugins/Kotlin/kotlinc/bin/kotlinc`
with `-Xplugin=…/kotlinc/lib/kotlinx-serialization-compiler-plugin.jar` and a
classpath of Maven jars (kotlinx-serialization-json/core, okhttp, okio-jvm,
kotlinx-coroutines-core-jvm). Compiles every `core/*.kt` except
`KeychainStore.kt` (androidx). Faster than a Gradle round-trip.
## API gotchas (all handled in code — don't regress)
- **Single-encode URLs.** Ids stay RAW in `McmsEndpoint`; `ApiClient` encodes the
path once via `HttpUrl.addPathSegments`. Pre-encoding double-encoded MAC colons
(`:` → `%3A` → `%253A`) → MCMS "invalid id".
- **401 bounces to login; 403 does NOT** (permission/CSRF — `requiresReauthentication`
is 401-only).
- **Writes return `{"status":"success"}` with no `data`** — the unwrap tolerates it.
- **ONU registration lives on OLT-STATE buckets** (`OltRepository.registrationMap`),
not ONU-STATE. Friendly names are `ONU.Name` / `OLT.Name` (NOT `NETCONF.Name`).
- **CPE DHCP** comes from the web helper `GET /api/cpe/onu/<id>/` — a versionless,
bare `[code, cpe…]` array (use `ApiClient.getRaw`).
- **Firmware** = Procedure 7: GET ONU-CFG → write filename/version into the
**inactive** bank → full-doc PUT (`FirmwareUpgrade.apply`). Inactive-bank only,
so service stays up until the ONU reboots. Still worth testing on a spare ONU.
- Field paths were confirmed against live JSON; see `docs/MCMS_API.md` and the
model accessors.
## Trimmed vs iOS (intentional, easy to restore)
- ONU detail tabs are **Overview / CPE / Logs / Config** — no separate Alarms tab.
Current alarms live on ONU-STATE `"Alarm"` buckets if you want to add it.
- **Config** shows pretty-printed JSON text, not the collapsible tree the iOS app
has.
- Dashboard **ONU-state rows aren't tappable** (the Health rows are). The iOS app
drills ONU-state → filtered ONU list.
- Toggles use `rememberSaveable` (survive rotation, not process death). Persist in
prefs if you want parity with iOS `@AppStorage`.
- Self-signed/cleartext: the TLS trust policy is in `ServerTrust`. Plain-HTTP hosts
also need a `usesCleartextTraffic`/network-security-config exception (Android's
ATS analogue) — add when needed.
## Repo split
This folder is self-contained (has its own `docs/MCMS_API.md`). To make it a git
repo: `git init` here; the included `.gitignore` already excludes `build/`,
`.gradle/`, `local.properties`, `.idea/`. Commit the Gradle wrapper
(`gradlew`, `gradle/wrapper/*`). The full dev-guide PDFs (`323-1961-30x`) live in
the iOS repo if you ever need the deep source.
## Possible next steps
Restore the trimmed items above; add OLT firmware (Procedure 8 bulk task);
per-ONU live-alarms view; charts for PM history; pull-to-refresh on lists;
dark-theme polish; a proper app theme from the brand colours.