Commit graph

2 commits

Author SHA1 Message Date
kianiadee
7d63c03191 Trip detection: add nofix_stop rule (5-min reporting silence ends trip)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Calibrated against a full-day legacy report for vehicle KDE 638J:
without this rule we collapsed 15 dispatcher-visible trips into 3
(the algorithm waited for explicit ACC_OFF + stationary fixes that never
came in the polled data — the device just stops reporting between trips).

New rule: if mid-trip and the next fix arrives >=5 min after the previous
one (but <=30 min, which is still long_gap), close the trip at the prior
fix with end_reason='nofix_stop'.

Validation:
  638J full day: legacy 15 trips, mine 15 trips, perfect alignment
  728K half day: legacy 33 noisy trips, mine 9 clean trips
                 (stop-and-go traffic still consolidates because fixes
                  keep coming, just slow/stationary — not silence)

Also commits scripts/simulate_trips_from_legacy.py which runs the same
state machine in Python against REPORTS/*.json dumps for offline tuning.
2026-05-27 12:57:01 +03:00
kianiadee
419c030761 Trip detection backend: serve.fn_vehicle_trips + JSON/CSV endpoints
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
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