No description
Find a file
kianiadee 419c030761
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Trip detection backend: serve.fn_vehicle_trips + JSON/CSV endpoints
Migration 19: serve.fn_vehicle_trips(vehicle_id, date) — PL/pgSQL state
machine that walks state.position_history for one vehicle on one EAT day
and emits the trip breakdown. Rules:

  - reporting_time = first ACC_ON of the day
  - trip starts at ACC_ON (or first fix if already ACC_ON / moving)
  - trip ends:
      * ACC_OFF + stationary (<5 km/h) for >=5 min  → end_reason 'work_stop'
      * fix gap >30 min                              → end_reason 'long_gap'
      * end of day's data                            → end_reason 'day_end'
  - within a trip, ACC_ON + stationary >=5 min is logged as an idling
    segment (no trip split — engine still on)
  - distance only accumulates when speed >= 5 km/h (excludes GPS jitter)
  - falls back to movement-only segmentation when acc_state is null
    across the day (has_acc_data=false in the response)

Returns one jsonb document: vehicle, date, reporting_time, day totals
(distance, driving/idling/stopped/unknown minutes), data_quality flags,
trips[] with start/end/duration/distance/idling/end_reason/stops/path
where path is a GeoJSON LineString ready for the map.

New endpoints (read:fleet, rate-limited):
  GET /api/views/vehicle/{id}/trips?date=YYYY-MM-DD       JSON
  GET /api/views/vehicle/{id}/trips.csv?date=YYYY-MM-DD   one row per trip

Defaults date to today in EAT (UTC+3) regardless of host TZ.
2026-05-27 12:24:00 +03:00
.forgejo/workflows Add workflow_dispatch trigger 2026-05-23 01:06:18 +03:00
app Trip detection backend: serve.fn_vehicle_trips + JSON/CSV endpoints 2026-05-27 12:24:00 +03:00
db/migrations Trip detection backend: serve.fn_vehicle_trips + JSON/CSV endpoints 2026-05-27 12:24:00 +03:00
scripts Rollback CSV roster import (mig 17): re-split vehicles, drop CSV columns 2026-05-25 00:41:32 +03:00
tests Parser: tolerate real Tracksolid wire shape (imei/speed names, null gpsTime for offline devices) + per-item resilience 2026-05-23 09:05:17 +03:00
web UX: zoom-scaled vehicle markers + hide labels at city overview 2026-05-27 12:07:50 +03:00
.env.example UI: arrow + plate-short label + cost-centre marker palette + hover popup; richer state.live_positions + serve.fn_live_view v2; multi-target poll plumbing 2026-05-23 09:29:04 +03:00
.gitignore Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00
260522_fleet_platform_architecture_final.md Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00
260522_fleet_platform_prd_final.md Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00
20260427_FSG_Vehicles_mitieng.csv Roster import: COALESCE-fill API-managed fields (device_type/lifecycle/activation_at/model) on existing rows; CSV is authoritative only for driver/phone/iccid/expiration/device_group 2026-05-24 03:59:32 +03:00
docker-compose.dev.yml Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00
Dockerfile Gateway: serve web/ at root via StaticFiles; redirect / to /index-live.html 2026-05-23 01:35:13 +03:00
LICENSE Initial commit 2026-05-22 17:35:05 +00:00
pyproject.toml Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00
README.md README: note CI live 2026-05-23 01:12:36 +03:00

fleet-platform

Greenfield rebuild of the Rahamafresh fleet telematics platform — CI is live on Forgejo Actions.

One FastAPI codebase, one Docker image, three container roles (gateway / worker / cron) from the same image. Event-sourced ingest into TimescaleDB + PostGIS. JWT-mandatory reads. Image-tag deploys via Coolify from a self-hosted Forgejo registry.

See:

  • 260522_fleet_platform_prd_final.md — product spec (P1P4)
  • 260522_fleet_platform_architecture_final.md — engineering design (phases AG)
  • ~/.claude/plans/you-are-an-experienced-majestic-planet.md — approved Phase 1 plan

Quick start (dev)

cp .env.example .env
# edit .env: at minimum set POSTGRES_PASSWORD, JWT_SECRET, TRACKSOLID_PUSH_TOKEN
docker compose -f docker-compose.dev.yml up

Health checks:

curl http://localhost:8001/health/gateway
curl http://localhost:8001/health/worker   # via worker container's exposed port
curl http://localhost:8001/health/cron

Layout

app/                   one FastAPI codebase
  entrypoints/         three role entrypoints from the same image
    gateway.py         /push/jimi/*, /api/views/*, /api/auth/token
    worker.py          LISTEN parser + projectors
    cron.py            polling + SLO + contract checker
  models/              Pydantic models (Jimi contracts, view shapes)
  parsers/             one function per msg_type / poll endpoint
  projectors/          single-writer projectors per state table
db/migrations/         dbmate forward-only SQL
scripts/               operational utilities (parity_check, entrypoint.sh)
tests/                 pytest
web/                   fleet-core.js + index-live.html + login.html

Container roles

The same image runs in three roles, selected by APP_ROLE:

Role Workload
gateway HTTP: Tracksolid push receivers + dashboard read API + JWT issuance
worker LISTEN events_raw_new / events_parsed_new → parser → projectors
cron APScheduler: polled ingest (60s/10m), SLO measurement, contract checker

Failure isolation is the point: a heavy report in worker does not stall gateway.

Deploy

CI (Forgejo Actions) builds on push to main, tags <registry>/fleet-platform:<sha> and :latest. Coolify deploys by tag. Rollback is coolify deploy :<prev-sha>.

dbmate up runs on platform-worker startup before the worker serves traffic; gateway and cron wait on a startup probe that confirms migration completion.