an open source Park Smarter alternative. Works with IPS parking meters.
Find a file
Hank d1473f9776 Scanner: parse processQR URLs, manual Zone ID entry, zone-name fallback
Kiosk QR decoded to a bare https://www.parksmarter.com/home/processQR (no zone) —
even the official app rejects code-less URL QRs. Now: parse processQR?code= URLs,
detect bare app-link QRs and prompt for the printed Zone ID, and add manual Zone ID
entry. Lookups try getMetersByScannerCode then getMetersByZoneName (DSB13 maps to
zone 113150). Fixes scanning real stickers, which previously passed the URL to the API.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:38:38 -07:00
.gitea/workflows Initial commit: parksmarter-client + BigBrainParking app 2026-07-06 08:33:47 -07:00
app Scanner: parse processQR URLs, manual Zone ID entry, zone-name fallback 2026-07-06 12:38:38 -07:00
docs docs: clarify Obtainium reads repo Releases (not Packages) 2026-07-06 08:36:26 -07:00
parksmarter-client Detect declined sessions (200 + Status:Error); theme Sessions screen 2026-07-06 12:25:14 -07:00
.gitignore Initial commit: parksmarter-client + BigBrainParking app 2026-07-06 08:33:47 -07:00
package-lock.json Add on-device debug logging: file capture + share (for real-session testing) 2026-07-06 11:59:41 -07:00
package.json Initial commit: parksmarter-client + BigBrainParking app 2026-07-06 08:33:47 -07:00
README.md Initial commit: parksmarter-client + BigBrainParking app 2026-07-06 08:33:47 -07:00

BigBrainParking

An unofficial, de-Googled client for the ParkSmarter (IPS Group) parking system, built to run on GrapheneOS with UnifiedPush notifications and distributed via Obtainium — no Google Play Services, no Firebase, no app store.

Monorepo layout

bigbrainparking/
├── parksmarter-client/   # Zero-dep TypeScript API client (reverse-engineered, live-verified)
├── app/                  # Expo / React Native app (BigBrainParking)
└── .gitea/workflows/     # CI: build signed APK -> publish release for Obtainium
  • parksmarter-client — the API layer. All ~40 endpoints, the custom-header auth model, and response models (most verified against production). Runs anywhere; the app imports it directly. See its own README for the API details.
  • app — the phone app. React Native (Expo prebuild), MapLibre maps, VisionCamera QR scanning, expo-secure-store token storage, local session-expiry reminders, and UnifiedPush wiring.

Features

Feature Status Notes
Phone + password login wired tokens in OS keystore
Map of nearby meters (clickable, zoom, live GPS) wired MapLibre + OpenFreeMap tiles (no key)
"Near my last location" proximity search wired caches last GPS fix
QR kiosk scan → meter lookup wired on-device VisionCamera
Save / share kiosks wired local (no server favorites API exists)
Active / past sessions wired list views
Start a paid session 🟡 gated flow wired to postStartParkingSession, disabled pending review (real charge)
Session-expiry reminders wired local notifications — no FCM needed
UnifiedPush (ntfy) 🟡 partial endpoint registration done; server→ntfy bridge still needed (see below)

Build & run (dev)

Requires Node 20, JDK 17, Android SDK, and a GrapheneOS device (or any Android device) with USB debugging.

npm install                                   # installs both workspaces
npm run build --workspace parksmarter-client  # compile the client
cd app
npx expo prebuild --platform android          # generate native project
npx expo run:android                          # build + install a dev client

The app talks to prod (apiv2.parksmarter.com) by default — change extra.psEnvironment in app/app.json to point elsewhere.

Notifications on GrapheneOS

Session-expiry reminders are scheduled locally from each session's end time, so they need no push infrastructure and work fully offline of Google. app/src/notifications/ also wires UnifiedPush (distributor: ntfy) for any genuinely server-initiated push — but note the ParkSmarter backend only pushes via FCM, so server push requires a small FCM→ntfy bridge (a service holding an FCM token that forwards to your ntfy topic, then registered via PUT /api/Device). Until that exists, local reminders cover the main case.

Distribution via Obtainium (self-hosted)

Tag a release and CI builds a signed APK and publishes it to this repo's releases; your phone's Obtainium tracks the repo and offers updates. See docs/DISTRIBUTION.md for the full server + CI + keystore setup.