Cargo-Pro — residue-aware loading for coal rail
TL;DR
We track each rail carriage with RFID, capture gross + tare at the power plant, compute actual residue, and tell loaders exactly how much to top up on the next cycle. A lightweight GCP web app + a couple of Cloud Functions + MS SQL (RFID reads) + MongoDB (app data) tie it together. Result: +12% effective loading year-over-year, with fewer overloads and far fewer underloads.
Introduction
At the mine, loaders used to “go by feel.” The legal cap is 90t per carriage. In reality, carriages come back dirty — 2t, 5t, sometimes 7t of leftover coal—so fixed presets don’t work. Cargo-Pro closes that loop: we measure what actually left the plant (gross vs. tare), match it to the returning carriage via RFID, and give the loader a target number that lands just under 90t, residue included.
What made it hard
- Residue is unpredictable. It varies per carriage and per trip.
- IDs in the wild. RFID reads can be noisy; not every loader loves scanning things.
- Two worlds, two clocks. Plant scales vs. mine yard scanners—different systems, imperfect connectivity.
- Human factors. A target is only useful if the UI is fast, legible, and forgiving on a cold night shift.
Architecture at a glance
High-level pieces: 1. RFID ingestion (MS SQL): Antennas log scans at weighbridges. 2. Weighbridge data: At the plant, each carriage is weighed twice: gross (loaded), then tare (after deload). 3. Cloud functions (GCP): Match scans → compute residue → calculate next-load target. 4. App Engine web app: Admin tools, worker UI, and performance dashboards. 5. MongoDB: Application truth (carriages, cycles, workers). 6. Sync jobs: Push/pull between MS SQL (raw scans) and MongoDB (normalized domain data).
Flow, in practice
- Outbound: A loaded carriage is weighed at the plant (RFID #1 + gross).
- Deload: Coal is emptied to the electric plant.
- Post-deload: The same carriage is weighed again (RFID #2 + tare). Net shipped = gross − tare.
- Return: The empty carriage travels ~300km back to the mine.
- Identify: Loader scans the carriage QR or types a 4-digit code (RFID is auto if available).
- Guidance: The app shows “Load X t”—a residue-aware target that aims just under 90t.
- Load: Worker fills to target; carriage heads back to the plant.
- Repeat: Each cycle refines the next recommendation.
How the math works (plain language)
- Residue for a carriage is inferred from the tare after deload vs. its clean baseline.
- Next target = 90t − (estimated residue on return) − a small safety margin.
- If scans conflict or a weight looks off, we flag and fallback to a conservative rule (and tell the loader why).
Data model (simplified)
- carriages: rfid, short_code, baseline_tare, status.
- cycles: carriage_id, timestamps (gross, tare, return), weights, residue_estimate, recommendation, safety_margin, flags.
- workers: id, role, active, hashed identifiers.
- events: scan reads, overrides, load confirmations (for audits).
Worker & admin UX
- Loader screen: One big number, “Load 27.4t”, plus context (“Last residue: 5.8t”).
- After action: Loader taps Confirm; we store who, when, and what was actually loaded.
- Admin panel: Manage carriages & workers; leaderboard and variance charts (recommended vs. actual), filter by shift/date/carriage; anomaly inbox for bad scans.
Reliability, ops, and cost
- Idempotent matching: Cloud Functions use deterministic keys per cycle to avoid dupes from repeated scans.
- Connectivity hiccups: Local queue on the yard scanner; Cloud Functions retry with backoff.
- Observability: Correlation IDs per carriage cycle, logs around outlier weights, and a daily “unmatched scans” report.
- Security & compliance: Role-based access; immutable audit trail for any manual override.
- Cost: App Engine standard + Functions keep baseline near zero when trains aren’t moving.
Edge cases we handle
- Duplicate/late scans: De-dupe on (rfid, time window, bridge).
- Weighbridge drift: Soft alerts if tare deviates from baseline beyond tolerance.
- No RFID read: Fall back to QR/4-digit code; reconcile later when scans arrive.
- Suspicious weights: Flag, reduce target, and require supervisor acknowledgement.
Results that mattered
- +12% effective loading vs. previous year (more coal moved per carriage on average).
- Fewer overload incidents while shrinking underloads—the sweet spot moved closer to 90 t without crossing it.