A personal tool for extracting LiveMopay electricity ledger rows locally, syncing them to Supabase, and viewing usage, spend, balance, fixed charges, and tariffs in a deployed Next.js dashboard.
Livenopay now separates ingestion from presentation:
- local machine: runs Android/ADB capture through
capture_livemopay.py - local machine: syncs the resulting
livemopay_energy.csvto Supabase withrefresh_and_sync.py - Supabase: source of truth for dashboard reads
- deployed Next.js app: reads Supabase only and never triggers Android/ADB
There are no job queues, polling workers, remote command systems, or localhost dependencies for viewing the dashboard.
This repo is set up as a personal deployable tool, not a shared hosted product.
If someone else wants to use it, they should run their own instance:
- create their own Supabase project
- apply the Supabase migration from this repo
- deploy their own Next.js dashboard with their own Supabase read env vars
- run
refresh_and_sync.pylocally on the machine that can access their Android phone or emulator
The deployed dashboard only reads Supabase. It does not know how to capture someone else's LiveMopay data, and it cannot trigger Android/ADB remotely.
To turn this into a product for multiple users, the architecture would need more work: authentication, per-user data isolation, a proper ingestion/onboarding story, and a backend that does not expose service-role access to clients. That is intentionally out of scope for this personal version.
Apply the migration in:
supabase/migrations/20260414000000_livenopay_energy.sql
It creates:
energy_rowswith the same core shape as the CSV:capture_dt,charge_label,period_dt,kwh,tariff,cost,balance- a natural unique key on
charge_label,period_dt,cost, andbalance capture_runsfor sync metadata used by the dashboard's last synced indicator
The unique key matches the existing local capture dedupe strategy, so rerunning sync is idempotent and avoids duplicate rows.
For the deployed dashboard:
SUPABASE_URL=...
SUPABASE_ANON_KEY=...
For local sync:
SUPABASE_URL=...
SUPABASE_SERVICE_ROLE_KEY=...
You can put these in .env.local for local development. Do not expose the service role key in the browser or deployed public client environment.
npm install
npm run dev
Open http://localhost:3000.
The dashboard and data table read from Supabase through src/lib/energy-data.ts. They do not read livemopay_energy.csv directly.
On the local machine that has Android/ADB configured, run:
python3 refresh_and_sync.py
or:
npm run refresh
That command:
- runs
python3 capture_livemopay.py - reads the refreshed
livemopay_energy.csv - upserts all CSV rows into Supabase
- records a
capture_runsrow for last synced metadata
For a full local recapture before syncing:
python3 refresh_and_sync.py --full
To sync the existing CSV without touching Android/ADB:
python3 refresh_and_sync.py --skip-capture
Rows are normalized in src/lib/csv.ts, then summarized in src/lib/analytics.ts.
Analytics behavior is preserved:
- fixed daily charges are included in total spend
- fixed daily charges are excluded from kWh, hourly usage, and tariff analysis
- top-ups appear in raw data and balance history context
- top-ups are excluded from electricity spend
capture_livemopay.py remains local-only and still depends on ADB plus a connected Android phone or emulator. See SETUP.md for the Android setup.
The deployed dashboard cannot run capture. Refreshing data is a manual local command by design.
src/app- App Router pagessrc/components/dashboard- dashboard controls and insight sectionssrc/components/charts- Recharts chart componentssrc/components/data- Supabase-backed data tablesrc/components/ui- shared presentation componentssrc/lib- Supabase access, CSV normalization, filtering, formatting, and analyticssupabase/migrations- database schemacapture_livemopay.py- local Android capturerefresh_and_sync.py- local capture and Supabase sync