Compare commits

..

No commits in common. "main" and "260521-location-freshness-upgrade" have entirely different histories.

83 changed files with 455 additions and 28382 deletions

View file

@ -1 +0,0 @@
{"sessionId":"c108db62-4596-4e11-a4d2-c706487747bf","pid":15863,"acquiredAt":1776761841807}

3
.gitignore vendored
View file

@ -13,9 +13,6 @@ __pycache__/
# OS # OS
.DS_Store .DS_Store
# OSM extracts (large, reproducible from download — see docs/OSM_POI_EXPORT.md)
*.osm.pbf
Thumbs.db Thumbs.db
# Backups # Backups

View file

@ -432,27 +432,6 @@ WHERE d.device_name = 'FRED KMGW 538W HULETI'
ORDER BY ph.gps_time ASC; ORDER BY ph.gps_time ASC;
``` ```
<!-- distinct routes per vehicle -->
``` sql
SELECT
ph.gps_time AT TIME ZONE 'Africa/Nairobi' AS gps_time_eat,
ROUND(ph.lat::numeric, 5) AS lat,
ROUND(ph.lng::numeric, 5) AS lng,
ph.speed,
ph.direction,
ph.acc_status,
ph.source
FROM tracksolid.position_history ph
JOIN tracksolid.devices d ON d.imei = ph.imei
WHERE d.device_name = 'FRED KMGW 538W HULETI'
AND ph.gps_time > now() - interval '24 hours'
ORDER BY ph.gps_time ASC;
'''
### Fix density per device — last 24 hours ### Fix density per device — last 24 hours
```sql ```sql
SELECT SELECT

View file

@ -1,14 +0,0 @@
{
"folders": [
{
"path": "."
},
{
"path": "../60_karuracc-test-app"
},
{
"path": "../62_ts_postman"
}
],
"settings": {}
}

107
CLAUDE.md
View file

@ -19,7 +19,7 @@ docker exec $DB psql -U postgres -d tracksolid_db -c "SELECT COUNT(*) FROM track
**Run a migration file:** **Run a migration file:**
```bash ```bash
docker exec -i $DB psql -U postgres -d tracksolid_db < migrations/07_your_migration.sql docker exec -i $DB psql -U postgres -d tracksolid_db < 07_your_migration.sql
``` ```
--- ---
@ -56,9 +56,8 @@ See `docs/CONNECTIONS.md` for the full shape. Summary:
- **SSH:** `ssh -i ~/.ssh/id_ed25519 kianiadee@stage.rahamafresh.com` - **SSH:** `ssh -i ~/.ssh/id_ed25519 kianiadee@stage.rahamafresh.com`
- **DB name:** `tracksolid_db` · **DB user:** `postgres` (internal) · `tracksolid_owner` (app) · `grafana_ro` (read-only) - **DB name:** `tracksolid_db` · **DB user:** `postgres` (internal) · `tracksolid_owner` (app) · `grafana_ro` (read-only)
- **DB schemas:** `tracksolid` (live, single source of truth) · `reporting` (map-dashboard read layer) · `infrastructure`. The legacy `tracksolid_2` schema no longer exists (migrations 0206, 2026-04-18); the `ops` and `dwh_gold` schemas were purged 2026-06-05 (migrations 12/13) as unused. - **DB schemas:** `tracksolid` (live, single source of truth) · `dwh_gold` (aggregates) · `ops` (workshop / tickets / odometer) · `infrastructure`. The legacy `tracksolid_2` schema no longer exists — migrations 0206 applied 2026-04-18.
- **DB access:** `DATABASE_URL` points to `timescale_db:5432` (internal Docker network — not reachable locally). Use `docker exec` pattern above. See `docs/CONNECTIONS.md` for full reference. - **DB access:** `DATABASE_URL` points to `timescale_db:5432` (internal Docker network — not reachable locally). Use `docker exec` pattern above. See `docs/CONNECTIONS.md` for full reference.
- **DWH target DB:** `tracksolid_dwh` at `31.97.44.246:5888` (separate PostGIS instance, public IP). Users: `dwh_owner` (bronze writes + `dwh_control`), `grafana_ro` (reads bronze/silver/gold/`dwh_control`). Always connect with `sslmode=require`. Fed by the n8n `dwh_extract` + `dwh_load_bronze` workflows — see `docs/DWH_PIPELINE.md`.
- **Container naming:** Coolify appends a random suffix. Always resolve with: - **Container naming:** Coolify appends a random suffix. Always resolve with:
```bash ```bash
docker ps --filter name=<service_name> --format "{{.Names}}" | head -1 docker ps --filter name=<service_name> --format "{{.Names}}" | head -1
@ -66,25 +65,6 @@ See `docs/CONNECTIONS.md` for the full shape. Summary:
e.g. `docker ps --filter name=timescale_db --format "{{.Names}}" | head -1` e.g. `docker ps --filter name=timescale_db --format "{{.Names}}" | head -1`
- **Env vars:** loaded from `.env` via `env_file` in `docker-compose.yaml`. See `docs/CONNECTIONS.md` for variable names. Never hardcode secrets. - **Env vars:** loaded from `.env` via `env_file` in `docker-compose.yaml`. See `docs/CONNECTIONS.md` for variable names. Never hardcode secrets.
### Map dashboards & read-API
The map UIs read the **`dashboard_api`** service (FastAPI, `dashboard_api_rev.py`) at
`https://fleetapi.rahamafresh.com` — the stable replacement for the retired n8n webhooks. It serves
GeoJSON from the `reporting.*` functions (`fn_live_positions`, `fn_vehicle_track`, `fn_trips_for_map`)
+ filter options. **`dashboard_api` is a STANDALONE Traefik-labelled bridge container, NOT Coolify-managed** —
it bind-mounts the host file `~/dashboard_api/dashboard_api_rev.py` and is (re)deployed by
`~/deploy_dashboard_api.sh` on the host (an env/CORS change needs a *recreate*, not a restart). Three
single-page apps consume it:
| Dashboard | What | Hosting |
|---|---|---|
| `liveposition.rahamafresh.com` | live positions only | `index.html` in rustfs bucket `liveposition` behind an nginx proxy |
| `fleetintelligence.rahamafresh.com` | historical trips only | `index.html` in rustfs bucket `fleetintelligence` behind an nginx proxy |
| `fleetnow.rahamafresh.com` | **merged** live + trips (current best UI) | **own repo** `repo.rahamafresh.com/kianiadee/fleetnow.git`, deployed via **Coolify (Dockerfile → nginx)** |
All three origins must be in the API's `DASHBOARD_CORS_ORIGINS` (see FIX-D03). **FleetNow is the
single source of truth for the merged map and lives in its own repo — edit it there, not here.**
--- ---
## 4. Codebase Map ## 4. Codebase Map
@ -100,34 +80,20 @@ run_migrations.py # Applies SQL migrations in order at container start
docker-compose.yaml # Services: timescale_db, ingest_movement, ingest_events, docker-compose.yaml # Services: timescale_db, ingest_movement, ingest_events,
# webhook_receiver, grafana # webhook_receiver, grafana
grafana/ # Grafana provisioning (baked into image) grafana/ # Grafana provisioning (baked into image)
n8n-workflows/ # n8n workflow exports (incl. dwh_extract, dwh_load_bronze) n8n-workflows/ # n8n workflow exports
docs/ # Reference docs (connections, API, KPIs, project context) docs/ # Reference docs (connections, API, KPIs, project context)
docs/PLATFORM_OVERVIEW.html # Current-state platform reference (architecture, deploy, read-API,
# full DB schema, Grafana panels) — open in a browser. Post n8n→fleetapi.
docs/DWH_PIPELINE.md # DWH pipeline operations runbook (setup, troubleshooting)
docs/OSM_POI_EXPORT.md # Runbook: OSM .pbf → POI GeoJSON → FleetNow map layer (Shell stations)
docs/superpowers/ # Pitch specs and implementation plans (not deployed code) docs/superpowers/ # Pitch specs and implementation plans (not deployed code)
scripts/export_osm_pois.py # OSM .pbf → GeoJSON+CSV POI exporter (amenity/brand filter); see OSM_POI_EXPORT.md 02_tracksolid_full_schema_rev.sql # Full schema bootstrap
dwh/ # DWH migrations for tracksolid_dwh@31.97.44.246:5888 03..06_*.sql # Incremental migrations (06 adds assigned_city, dispatch_log, ops.*)
# 260423_dwh_ddl_v1.sql — bronze/silver/gold schemas + roles 07_analytics_views.sql # Analytics views migration (applied 2026-04-21)
# 261001_dwh_control.sql — watermarks + run log
# 261002_bronze_constraints_audit.sql — ON CONFLICT key assertion
# 261003_dwh_roles.sql — role contract assertion
# 261004_dwh_observability_views.sql — freshness/failure views
migrations/ # Numbered SQL migrations 0213, applied in order by run_migrations.py
# 02 full schema · 03 webhook · 04 distance fix · 05 enhancements
# 06 ops/analytics · 07 views · 08 config · 09 trips enrichment
# 10_driver_clock_views.sql · 10_pgbouncer_auth.sql · 11 reporting
# 12 drop ops schema · 13 drop dwh_gold schema (both 2026-06-05)
Dockerfile # Custom image for ingest/webhook containers Dockerfile # Custom image for ingest/webhook containers
pyproject.toml # Python project + uv dependency spec pyproject.toml # Python project + uv dependency spec
OPERATIONS_MANUAL.md # Day-to-day ops runbook
backup/ # pg_dump sidecar scripts and config backup/ # pg_dump sidecar scripts and config
data/ # Source CSVs (FS Logistics 144-device list, FSG vehicles) 01_BusinessAnalytics.md # SQL analytics library — read before writing queries
legacy/ # Superseded pre-_rev scripts + old pipeline notes (NOT deployed) 20260414_FS__Logistics - final_fixed.csv # 144-device driver/vehicle source data
docs/manuals/ # OPERATIONS_MANUAL, grafana + DWH manuals, docker commands, DB manual tracksolidApiDocumentation.md # API endpoint reference
docs/reference/ # 01_BusinessAnalytics.md (SQL library — read before writing queries), 260412_baseline_report.md # Fleet state snapshot (Apr 2026)
# tracksolidApiDocumentation.md, 260507_pgbouncer_deployment.md
docs/reports/ # Baseline reports, audit output, improvement reviews
``` ```
--- ---
@ -148,13 +114,12 @@ tracksolid.alarms -- Alarm events (alarm_type, alarm_name, alarm_time
tracksolid.obd_readings -- OBD diagnostics (push only, awaiting webhook registration) tracksolid.obd_readings -- OBD diagnostics (push only, awaiting webhook registration)
tracksolid.device_events -- Power on/off tamper events (push only) tracksolid.device_events -- Power on/off tamper events (push only)
tracksolid.ingestion_log -- API call audit trail — 875 runs / 24h, 0 failures at last check (2026-04-19) tracksolid.ingestion_log -- API call audit trail — 875 runs / 24h, 0 failures at last check (2026-04-19)
tracksolid.schema_migrations -- Applied migrations 0213 tracksolid.dispatch_log -- Dispatch decisions for SLA tracking (migration 06; empty until ops integration)
-- PURGED 2026-06-05 (migrations 12 + 13): the dormant `ops` schema (tickets, service_log, tracksolid.schema_migrations -- Applied files: 02,03,04,05,06 (last 06 on 2026-04-18)
-- odometer_readings, cost_rates, kpi_targets, vw_service_forecast), tracksolid.dispatch_log, dwh_gold.fact_daily_fleet_metrics -- Nightly ETL aggregates per vehicle per day (run refresh_daily_metrics)
-- and the `dwh_gold` schema (dim_vehicles, fact_daily_fleet_metrics, refresh_daily_metrics). ops.service_log -- Workshop service history (migration 06)
-- Those workshop/dispatch/SLA/utilisation features were never implemented. Do NOT reintroduce ops.odometer_readings -- Physical odometer captures (migration 06)
-- references to ops.* or dwh_gold.* — they no longer exist. (The separate tracksolid_dwh DB ops.tickets -- Ticket skeleton for ops integration (migration 06; empty)
-- at 31.97.44.246:5888 is unrelated and untouched.)
``` ```
Full DDL: `02_tracksolid_full_schema_rev.sql` + migrations `03``06`. Full DDL: `02_tracksolid_full_schema_rev.sql` + migrations `03``06`.
@ -169,36 +134,17 @@ tracksolid.v_currently_idle -- §2.2 idle lens
tracksolid.v_driver_aggregates_daily -- §3.1 + §3.2 aggression index source tracksolid.v_driver_aggregates_daily -- §3.1 + §3.2 aggression index source
tracksolid.v_fleet_km_daily -- §7 Panel 5 distance trend tracksolid.v_fleet_km_daily -- §7 Panel 5 distance trend
tracksolid.v_alarms_daily -- §7 Panel 7 alarm frequency tracksolid.v_alarms_daily -- §7 Panel 7 alarm frequency
-- v_utilisation_daily (dwh_gold) and v_sla_inflight (ops) were DROPPED 2026-06-05 with tracksolid.v_utilisation_daily -- §7 Panel 8 utilisation heatmap (gated on dwh_gold ETL)
-- their schemas (migrations 12/13); their Grafana panels were removed from the dashboard. tracksolid.v_sla_inflight -- §4.5 SLA panels (gated on ops.tickets)
``` ```
All views carry a `COMMENT ON VIEW` referencing their spec — `\d+ tracksolid.v_*` shows the provenance. All views carry a `COMMENT ON VIEW` referencing their spec — `\d+ tracksolid.v_*` shows the provenance.
**DWH bronze layer (separate DB `tracksolid_dwh`)** — populated by the n8n `dwh_extract` + `dwh_load_bronze` workflows. Operational details in `docs/DWH_PIPELINE.md`.
```sql
-- bronze schema mirrors tracksolid.* (16 tables, DDL in dwh/260423_dwh_ddl_v1.sql)
bronze.devices, bronze.live_positions -- snapshot tables (TRUNCATE + reload)
bronze.position_history, bronze.trips,
bronze.alarms, bronze.parking_events,
bronze.device_events, bronze.ingestion_log -- incremental (watermark + ON CONFLICT DO NOTHING)
-- Schema drift: bronze.trips.distance_km vs source tracksolid.trips.distance_m
-- Extract SQL divides by 1000. Cross-ref FIX-M16.
-- dwh_control schema tracks pipeline state + observability
dwh_control.extract_watermarks -- one row per incremental table
dwh_control.extract_runs -- per-run audit log (status lifecycle)
dwh_control.v_table_freshness -- Grafana: load lag per table
dwh_control.v_recent_failures -- Grafana: failures in last 24h
dwh_control.v_watermark_lag -- Grafana: extract vs. load lag per table
```
--- ---
## 6. API Critical Facts ## 6. API Critical Facts
**Always read `docs/reference/tracksolidApiDocumentation.md` before adding a new endpoint call.** **Always read `tracksolidApiDocumentation.md` before adding a new endpoint call.**
| Fact | Detail | | Fact | Detail |
|---|---| |---|---|
@ -229,9 +175,6 @@ dwh_control.v_watermark_lag -- Grafana: extract vs. load lag per table
| FIX-M19 | `ts_shared_rev.py`, `ingest_movement_rev.py` | Multi-account support: fleet spans `fireside`, `Fireside@HQ`, `Fireside_MSA` (156 devices total). `sync_devices`, `poll_live_positions`, `poll_parking` iterate `TRACKSOLID_TARGETS` (comma-separated env var). New helper `get_active_imeis_by_target()` scopes parking calls to the right account | | FIX-M19 | `ts_shared_rev.py`, `ingest_movement_rev.py` | Multi-account support: fleet spans `fireside`, `Fireside@HQ`, `Fireside_MSA` (156 devices total). `sync_devices`, `poll_live_positions`, `poll_parking` iterate `TRACKSOLID_TARGETS` (comma-separated env var). New helper `get_active_imeis_by_target()` scopes parking calls to the right account |
| FIX-E06 | `ingest_events_rev.py` | Alarm field mapping: `alertTypeId`/`alarmTypeName`/`alertTime` | | FIX-E06 | `ingest_events_rev.py` | Alarm field mapping: `alertTypeId`/`alarmTypeName`/`alertTime` |
| BUG-02 | Migration 04 | Historical `distance_m` rows ÷1,000,000 → renamed to `distance_km` | | BUG-02 | Migration 04 | Historical `distance_m` rows ÷1,000,000 → renamed to `distance_km` |
| FIX-D01 | `dashboard_api_rev.py` | `POST /webhook/fleet-dashboard` read body as JSON, but the SPA posts `x-www-form-urlencoded``request.json()` threw, filters silently dropped, map always returned the whole fleet. Now parsed by Content-Type (`parse_qs` for form, JSON still accepted). Commit `f1387d1` |
| FIX-D02 | `dashboard_api_rev.py` | `reporting.v_trips` matview froze on 2026-06-01 when n8n (which ran the scheduled refresh) was retired → dashboard showed "no trips". Added an in-process background refresher (`REFRESH MATERIALIZED VIEW CONCURRENTLY` every `VTRIPS_REFRESH_INTERVAL_S`, default 300s; pg advisory-lock guarded for `--workers`; logs to `reporting.refresh_log` source=`dashboard_api`). Commit `30b3515` |
| FIX-D03 | `dashboard_api_rev.py`, `~/deploy_dashboard_api.sh` (host) | Added `https://fleetnow.rahamafresh.com` to `DASHBOARD_CORS_ORIGINS` default for the merged **FleetNow** dashboard. The standalone bridge container inherits its env from `webhook_receiver`, which already carries the old two-origin value — so the deploy script's *conditional* append never fired. The script now **strips any inherited `DASHBOARD_CORS_ORIGINS` and sets all three origins unconditionally**, and **guards the `mv`** so a missing staged `dashboard_api_rev.py` doesn't abort the run under `set -e` (env changes need a container *recreate*, not a restart). Commit `d95e5c2` |
--- ---
@ -239,14 +182,14 @@ dwh_control.v_watermark_lag -- Grafana: extract vs. load lag per table
1. **No prod push without explicit user confirmation.** Always state what you are about to push and wait. 1. **No prod push without explicit user confirmation.** Always state what you are about to push and wait.
2. **Never rewrite a migration that is already applied.** Check `tracksolid.schema_migrations` first. Add a new numbered migration file for any schema change. 2. **Never rewrite a migration that is already applied.** Check `tracksolid.schema_migrations` first. Add a new numbered migration file for any schema change.
3. **Read before writing.** Before suggesting any code change, read the relevant source file. Before writing a query, check `docs/reference/01_BusinessAnalytics.md` for an existing pattern. 3. **Read before writing.** Before suggesting any code change, read the relevant source file. Before writing a query, check `01_BusinessAnalytics.md` for an existing pattern.
4. **Reuse shared utilities.** All DB access via `get_conn()`, all API calls via `api_post()`, all cleaning via `clean()` / `clean_num()` / `clean_int()` / `clean_ts()` in `ts_shared_rev.py`. Do not reinvent these. 4. **Reuse shared utilities.** All DB access via `get_conn()`, all API calls via `api_post()`, all cleaning via `clean()` / `clean_num()` / `clean_int()` / `clean_ts()` in `ts_shared_rev.py`. Do not reinvent these.
5. **Resolve container names dynamically.** Never hardcode the Coolify suffix. Use `docker ps --filter name=<service>`. 5. **Resolve container names dynamically.** Never hardcode the Coolify suffix. Use `docker ps --filter name=<service>`.
6. **SSH only when asked.** Default workflow is local code → commit → push. SSH into the instance only when explicitly asked to test or run something live. 6. **SSH only when asked.** Default workflow is local code → commit → push. SSH into the instance only when explicitly asked to test or run something live.
7. **Secrets from env only.** Connection strings, API keys, and passwords live in `.env`. Reference variable names from `docs/CONNECTIONS.md`, never values. 7. **Secrets from env only.** Connection strings, API keys, and passwords live in `.env`. Reference variable names from `docs/CONNECTIONS.md`, never values.
8. **Two developers, one incoming.** Write code and docs that a second developer (mixed technical/operations background) can follow without prior context. 8. **Two developers, one incoming.** Write code and docs that a second developer (mixed technical/operations background) can follow without prior context.
9. **Forgejo API auth:** credentials stored in macOS keychain. Retrieve with `git credential fill` (host=repo.rahamafresh.com). Use basic auth against `https://repo.rahamafresh.com/api/v1` directly — no `tea` or `gh` needed. 9. **Forgejo API auth:** credentials stored in macOS keychain. Retrieve with `git credential fill` (host=repo.rahamafresh.com). Use basic auth against `https://repo.rahamafresh.com/api/v1` directly — no `tea` or `gh` needed.
10. **Single live schema.** All live data lives in `tracksolid`; the map-dashboard read layer lives in `reporting`. Do not reintroduce references to the retired `tracksolid_2`, `ops`, or `dwh_gold` schemas (the latter two purged 2026-06-05, migrations 12/13). 10. **Single live schema.** All live data lives in `tracksolid`. Aggregates live in `dwh_gold`; workshop/ticket integrations live in `ops`. Do not reintroduce references to the retired `tracksolid_2` schema.
--- ---
@ -265,7 +208,7 @@ dwh_control.v_watermark_lag -- Grafana: extract vs. load lag per table
| Cities active | Nairobi (primary), Mombasa (deploying), Kampala (4 devices in CSV) | | Cities active | Nairobi (primary), Mombasa (deploying), Kampala (4 devices in CSV) |
| Service flags | KDK 829A GP (239,264 km), Belta KCU-647D (235,000 km) | | Service flags | KDK 829A GP (239,264 km), Belta KCU-647D (235,000 km) |
Latest full snapshot: `docs/reports/260412_baseline_report.md` Latest full snapshot: `260412_baseline_report.md`
--- ---
@ -273,7 +216,6 @@ Latest full snapshot: `docs/reports/260412_baseline_report.md`
| Priority | Item | | Priority | Item |
|---|---| |---|---|
| HIGH | **Redeploy the Grafana service in Coolify** to apply `daily_operations_dashboard.json` — 5 panel areas (In-flight SLA, Idle Cost, Utilisation Heatmap, Row 7 Field-Service SLAs) that queried the now-dropped `v_sla_inflight`/`v_utilisation_daily` were removed. The DB views are already gone, so **live Grafana shows errors on those panels until the redeploy** (purge commit `8c5a43f`, 2026-06-05). |
| HIGH | Run `import_drivers_csv.py --apply` — 144 X3/JC400P devices with names + plates waiting | | HIGH | Run `import_drivers_csv.py --apply` — 144 X3/JC400P devices with names + plates waiting |
| HIGH | Register webhooks: `/pushoil` `/pushtem` `/pushlbs` (auto-register on push now done — commit 257643c) | | HIGH | Register webhooks: `/pushoil` `/pushtem` `/pushlbs` (auto-register on push now done — commit 257643c) |
| HIGH | Investigate X3-63282 in Kampala — legitimate or unauthorised? | | HIGH | Investigate X3-63282 in Kampala — legitimate or unauthorised? |
@ -281,5 +223,4 @@ Latest full snapshot: `docs/reports/260412_baseline_report.md`
| MEDIUM | Investigate 44 silent devices (only 19 of 63 reporting) — SIM installed? Activated? | | MEDIUM | Investigate 44 silent devices (only 19 of 63 reporting) — SIM installed? Activated? |
| MEDIUM | Co-develop client KPI framework (see `docs/KPI_FRAMEWORK.md`) | | MEDIUM | Co-develop client KPI framework (see `docs/KPI_FRAMEWORK.md`) |
| LOW | Populate geofences — depot boundaries, city zones | | LOW | Populate geofences — depot boundaries, city zones |
| HIGH | Deploy DWH bronze pipeline: apply `dwh/26100{1,2,3,4}.sql` to `tracksolid_dwh`, import + wire the two n8n workflows, verify first run via `dwh_control.v_table_freshness`. Runbook: `docs/DWH_PIPELINE.md` | | LOW | Schedule nightly ETL: `SELECT dwh_gold.refresh_daily_metrics(CURRENT_DATE - 1)` (cron or n8n) |
| MEDIUM | Rotate `dwh_owner` / `grafana_ro` passwords on `tracksolid_dwh` — plaintext in `dwh/260423_dwh_ddl_v1.sql` is a pre-existing flaw to clean up separately |

View file

@ -1,205 +0,0 @@
"""
audit_device_reconciliation.py 162-vs-182 device delta audit
Phase 0.2 of the Business Analytics redesign.
Compares `20260427_FSG_Vehicles_mitieng.csv` (162 rows) to `tracksolid.devices`
(182 rows at last check) and reports:
1. Per-account row counts on each side.
2. IMEIs in DB but not in CSV (the unexplained delta typically auto-synced
API rows with no business metadata).
3. IMEIs in CSV but not in DB (should be empty after a successful import).
4. IMEIs present on both sides where DB metadata is still NULL on key fields.
Usage:
# Read-only audit, prints to stdout.
python audit_device_reconciliation.py
# Same, but write output to a file (useful for the reconciliation report).
python audit_device_reconciliation.py --out 260427_audit_output.txt
# Use a different CSV path
python audit_device_reconciliation.py --csv path/to/file.csv
This script makes no writes safe to run on prod.
"""
import argparse
import csv
import sys
from collections import Counter
from pathlib import Path
from ts_shared_rev import get_conn, get_logger
log = get_logger("device_audit")
DEFAULT_CSV_PATH = Path(__file__).parent / "20260427_FSG_Vehicles_mitieng.csv"
# Fields whose NULL-ness on devices that DO appear in CSV would indicate
# a stale import.
META_FIELDS = ("assigned_city", "cost_centre", "assigned_route",
"vehicle_category", "vehicle_brand", "fuel_100km",
"depot_address", "driver_name", "vehicle_number")
def load_csv_index(csv_path: Path) -> dict[str, dict]:
rows: dict[str, dict] = {}
with open(csv_path, encoding="utf-8-sig", newline="") as f:
for row in csv.DictReader(f):
imei = (row.get("imei") or "").strip()
if imei:
rows[imei] = row
return rows
def load_db_index() -> dict[str, dict]:
cols = (
"imei", "account", "assigned_city", "city", "cost_centre",
"assigned_route", "vehicle_category", "vehicle_brand", "fuel_100km",
"depot_address", "driver_name", "vehicle_number", "device_name",
"last_synced_at", "created_at",
)
devices: dict[str, dict] = {}
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(f"SELECT {', '.join(cols)} FROM tracksolid.devices")
names = [d[0] for d in cur.description]
for row in cur.fetchall():
rec = dict(zip(names, row))
devices[rec["imei"]] = rec
return devices
def _csv_account(row: dict) -> str:
return (row.get("account") or "").strip() or "(blank)"
def _db_account(row: dict) -> str:
return (row.get("account") or "").strip() or "(blank)"
def _is_blank(v) -> bool:
if v is None:
return True
s = str(v).strip()
return s == "" or s.upper() == "NULL"
def main() -> int:
parser = argparse.ArgumentParser(description="Reconcile vehicle CSV against tracksolid.devices")
parser.add_argument("--csv", default=str(DEFAULT_CSV_PATH))
parser.add_argument("--out", default=None, help="Write report to this file in addition to stdout")
args = parser.parse_args()
csv_path = Path(args.csv)
if not csv_path.exists():
log.error("CSV not found: %s", csv_path)
return 1
csv_idx = load_csv_index(csv_path)
db_idx = load_db_index()
csv_imeis = set(csv_idx)
db_imeis = set(db_idx)
only_db = sorted(db_imeis - csv_imeis)
only_csv = sorted(csv_imeis - db_imeis)
both = csv_imeis & db_imeis
csv_accounts = Counter(_csv_account(r) for r in csv_idx.values())
db_accounts = Counter(_db_account(r) for r in db_idx.values())
out_lines: list[str] = []
def w(line: str = "") -> None:
out_lines.append(line)
print(line)
w("=" * 76)
w(" Device reconciliation — CSV vs tracksolid.devices")
w("=" * 76)
w(f" CSV file : {csv_path.name}")
w(f" CSV row count : {len(csv_idx)}")
w(f" DB row count : {len(db_idx)}")
w(f" Delta (DB-CSV) : {len(only_db):+d}")
w("")
w("─ Per-account breakdown ─────────────────────────────────────────────────")
all_accounts = sorted(set(csv_accounts) | set(db_accounts))
w(f" {'account':<30} {'CSV':>6} {'DB':>6} {'delta':>7}")
for acct in all_accounts:
c, d = csv_accounts.get(acct, 0), db_accounts.get(acct, 0)
w(f" {acct:<30} {c:>6} {d:>6} {d-c:>+7}")
w("")
w(f"─ IMEIs in DB but NOT in CSV ({len(only_db)}) ─────────────────────────────")
if not only_db:
w(" (none — DB is a strict subset of CSV)")
else:
w(f" {'imei':<18} {'account':<22} {'city':<10} {'last_synced_at':<28} {'device_name'}")
for imei in only_db:
r = db_idx[imei]
w(f" {imei:<18} {(r.get('account') or ''):<22} "
f"{(r.get('assigned_city') or r.get('city') or ''):<10} "
f"{str(r.get('last_synced_at') or ''):<28} "
f"{r.get('device_name') or ''}")
w("")
w(f"─ IMEIs in CSV but NOT in DB ({len(only_csv)}) ─────────────────────────────")
if not only_csv:
w(" (none — every CSV row has a corresponding device row)")
else:
w(f" {'imei':<18} {'account':<22} {'assigned_city':<14} {'cost_centre':<14} {'driver_name'}")
for imei in only_csv:
r = csv_idx[imei]
w(f" {imei:<18} {(r.get('account') or ''):<22} "
f"{(r.get('assigned_city') or ''):<14} "
f"{(r.get('cost_centre') or ''):<14} "
f"{r.get('driver_name') or ''}")
w("")
# Stale-metadata audit: in both, but DB is still NULL on key fields.
stale: list[tuple[str, list[str]]] = []
for imei in sorted(both):
d = db_idx[imei]
blanks = [f for f in META_FIELDS if _is_blank(d.get(f))]
if blanks:
stale.append((imei, blanks))
w(f"─ Devices in both, but DB metadata still NULL ({len(stale)}) ──────────────")
if not stale:
w(" (none — import looks complete on intersecting devices)")
else:
w(" Likely cause: import_drivers_csv.py has not been re-run with --apply")
w(" against the new CSV, or rows had 'Identification' placeholders.")
w("")
w(f" {'imei':<18} blank_fields")
for imei, blanks in stale[:30]: # cap output
w(f" {imei:<18} {', '.join(blanks)}")
if len(stale) > 30:
w(f" ... and {len(stale) - 30} more")
w("")
w("─ Suggested next step ───────────────────────────────────────────────────")
if only_db:
w(" Inspect the IMEIs above. Decide one of:")
w(" (a) Prune — delete from tracksolid.devices if they are stale "
"test/decommissioned units.")
w(" (b) Leave-as-NULL — keep them as auto-synced API rows; their "
"metadata stays NULL until added to a future CSV.")
w(" (c) Addendum — add them to the CSV (or a sidecar CSV) and re-run "
"import_drivers_csv.py --apply.")
w(" Document the choice in 260427_device_reconciliation.md.")
else:
w(" CSV and DB are reconciled. No further action.")
if args.out:
Path(args.out).write_text("\n".join(out_lines), encoding="utf-8")
print(f"\nReport also written to {args.out}")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -1,229 +0,0 @@
"""
backfill_trips_enrichment.py One-shot enrichment of historical tracksolid.trips rows
Migration 09 added route_geom, start/end_address, vehicle_plate, waypoints_count.
poll_trips() fills these for new trips going forward; this script backfills
existing rows where the new columns are NULL by reconstructing data from
position_history (the GPS trail is already there) and Nominatim.
Behaviour:
Selects rows where route_geom IS NULL OR start_geom IS NULL
(covers the original 8 historical poll-ingested trips and any future
rows that landed before position_history caught up).
Per row: runs the same 4-subquery enrichment poll_trips uses, then
reverse-geocodes start/end via Nominatim.
Writes only via COALESCE never overwrites webhook-supplied data.
Logs each run to tracksolid.ingestion_log with endpoint='backfill_trips_enrichment'.
Usage:
# Dry-run — shows counts only, writes nothing
python backfill_trips_enrichment.py
# Apply changes
python backfill_trips_enrichment.py --apply
# Scope to a single device
python backfill_trips_enrichment.py --imei 862798052707896 --apply
# Limit to trips since a date (UTC)
python backfill_trips_enrichment.py --since 2026-04-01 --apply
# Skip Nominatim reverse-geocoding (geometry/plate/idle only — runs in
# minutes instead of hours when backfilling thousands of rows). Addresses
# remain NULL for these rows and will be filled by future poll_trips
# cycles only for new trips, not retroactively.
python backfill_trips_enrichment.py --skip-geocode --apply
"""
import argparse
import time
from ts_shared_rev import (
get_conn,
get_logger,
log_ingestion,
reverse_geocode,
)
log = get_logger("backfill_trips")
_ENRICH_QUERY = """
SELECT
(SELECT geom FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_geom,
(SELECT ST_Y(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_lat,
(SELECT ST_X(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_lng,
(SELECT geom FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_geom,
(SELECT ST_Y(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_lat,
(SELECT ST_X(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_lng,
(SELECT ST_MakeLine(geom ORDER BY gps_time)
FROM tracksolid.position_history
WHERE imei = %s AND gps_time BETWEEN %s AND %s
AND geom IS NOT NULL) AS route_geom,
(SELECT COUNT(*) FROM tracksolid.position_history
WHERE imei = %s AND gps_time BETWEEN %s AND %s) AS waypoints_count
"""
def _select_targets(cur, imei: str | None, since: str | None) -> list[tuple]:
"""Return rows that need enrichment, as (id, imei, start_time, end_time)."""
sql = """
SELECT id, imei, start_time, end_time, vehicle_plate
FROM tracksolid.trips
WHERE (route_geom IS NULL OR start_geom IS NULL)
AND end_time IS NOT NULL
"""
params: list = []
if imei:
sql += " AND imei = %s"
params.append(imei)
if since:
sql += " AND start_time >= %s"
params.append(since)
sql += " ORDER BY start_time"
cur.execute(sql, params)
return cur.fetchall()
def _load_plates_cache(cur) -> dict[str, str]:
cur.execute("""
SELECT imei, vehicle_number
FROM tracksolid.devices
WHERE vehicle_number IS NOT NULL
""")
return {imei: plate for imei, plate in cur.fetchall()}
def run(apply: bool, filter_imei: str | None, since: str | None,
skip_geocode: bool = False) -> None:
t0 = time.time()
enriched = degenerate = no_fixes = failed = 0
if skip_geocode:
log.info("Reverse-geocoding disabled (--skip-geocode). Addresses will stay NULL.")
with get_conn() as conn:
with conn.cursor() as cur:
plates = _load_plates_cache(cur)
targets = _select_targets(cur, filter_imei, since)
log.info(
"Found %d trip(s) needing enrichment%s%s.",
len(targets),
f" for imei={filter_imei}" if filter_imei else "",
f" since={since}" if since else "",
)
for trip_id, imei, start_time, end_time, existing_plate in targets:
try:
cur.execute(_ENRICH_QUERY, (
imei, start_time,
imei, start_time,
imei, start_time,
imei, end_time,
imei, end_time,
imei, end_time,
imei, start_time, end_time,
imei, start_time, end_time,
))
(start_geom, start_lat, start_lng,
end_geom, end_lat, end_lng,
route_geom, waypoints_count) = cur.fetchone()
if waypoints_count == 0:
no_fixes += 1
log.info(
" trip id=%s imei=%s start=%s — no GPS fixes in window, skipping",
trip_id, imei, start_time,
)
continue
if waypoints_count < 2:
# Not enough fixes for a polyline. Still capture the
# single endpoint geom and address.
degenerate += 1
log.info(
" trip id=%s imei=%s — only %d fix(es), no route_geom",
trip_id, imei, waypoints_count,
)
if skip_geocode:
start_address = end_address = None
else:
start_address = reverse_geocode(start_lat, start_lng)
end_address = reverse_geocode(end_lat, end_lng)
vehicle_plate = existing_plate or plates.get(imei)
log.info(
" trip id=%s imei=%s waypoints=%d start=%s end=%s",
trip_id, imei, waypoints_count, start_address, end_address,
)
if apply:
cur.execute("""
UPDATE tracksolid.trips SET
start_geom = COALESCE(start_geom, %s),
end_geom = COALESCE(end_geom, %s),
route_geom = COALESCE(route_geom, %s),
waypoints_count = COALESCE(waypoints_count, %s),
start_address = COALESCE(start_address, %s),
end_address = COALESCE(end_address, %s),
vehicle_plate = COALESCE(vehicle_plate, %s)
WHERE id = %s
""", (
start_geom, end_geom, route_geom, waypoints_count,
start_address, end_address, vehicle_plate,
trip_id,
))
enriched += 1
except Exception:
failed += 1
log.warning(
"Failed to enrich trip id=%s imei=%s",
trip_id, imei, exc_info=True,
)
if apply:
log_ingestion(
cur, "backfill_trips_enrichment",
imei_count=len(targets),
upserted=0, inserted=enriched,
duration_ms=int((time.time() - t0) * 1000),
success=(failed == 0),
)
mode = "APPLIED" if apply else "DRY-RUN"
print(f"\n{'='*60}")
print(f" {mode} COMPLETE")
print(f"{'='*60}")
print(f" Trips enriched : {enriched}")
print(f" Degenerate (<2 fixes) : {degenerate}")
print(f" Skipped (no fixes) : {no_fixes}")
print(f" Failed : {failed}")
if not apply:
print("\n Run with --apply to commit changes.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Backfill route_geom / start_geom / end_geom / addresses on tracksolid.trips."
)
parser.add_argument("--apply", action="store_true", help="Write changes to DB (default: dry-run)")
parser.add_argument("--imei", default=None, help="Limit to a single IMEI")
parser.add_argument("--since", default=None, help="Only trips with start_time >= YYYY-MM-DD (UTC)")
parser.add_argument("--skip-geocode", action="store_true", help="Skip Nominatim reverse-geocoding (fast path for large backfills)")
args = parser.parse_args()
run(apply=args.apply, filter_imei=args.imei, since=args.since,
skip_geocode=args.skip_geocode)

View file

@ -1,324 +0,0 @@
"""
dashboard_api_rev.py Fireside Communications · Map Dashboard Read API
Stable replacement for the n8n webhooks that fed the Live Position and Fleet
Trips map dashboards. n8n was acting only as a thin HTTPSQL proxy; this
service does the same job directly against the proven reporting.* functions,
removing n8n's credential-management / reload / version-drift fragility from
the live-data path.
It REUSES the existing stack: ts_shared_rev's psycopg2 pool and DATABASE_URL,
the same Docker image, the same Coolify deploy. The reporting.* functions
(already verified to return correct GeoJSON) are the single source of truth.
Endpoints mirror the original n8n webhook paths so the only frontend change
is the base URL (the `N8N_BASE` constant in each dashboard SPA):
GET /webhook/live-positions?cost_centre=&acc_status=
{ summary, geojson } (reporting.fn_live_positions)
GET /webhook/live-positions/track?vehicle_number=&hours=
(alias: /webhook/vehicle-track)
GeoJSON Feature (reporting.fn_vehicle_track)
GET /webhook/fleet-dashboard
{ drivers, cost_centres, cities, vehicles } (filter options)
POST /webhook/fleet-dashboard body: {period, vehicle_numbers, driver,
cost_centre, assigned_city,
start_date, end_date}
trips payload (reporting.fn_trips_for_map)
GET /health
"""
from __future__ import annotations
import asyncio
import json
import os
import time
from contextlib import asynccontextmanager
from datetime import date, datetime, timedelta, timezone
from urllib.parse import parse_qs
import psycopg2
import psycopg2.extras
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from ts_shared_rev import close_pool, get_conn, get_logger
log = get_logger("dashboard_api")
# Comma-separated list of allowed browser origins (the dashboard domains).
_ALLOWED_ORIGINS = [
o.strip()
for o in os.getenv(
"DASHBOARD_CORS_ORIGINS",
"https://liveposition.rahamafresh.com,https://fleetintelligence.rahamafresh.com,https://fleetnow.rahamafresh.com",
).split(",")
if o.strip()
]
# ── v_trips materialized-view refresher ─────────────────────────────────────
# The Fleet Trips dashboard reads reporting.v_trips (a materialized view). Its
# refresh used to be a scheduled n8n workflow; when n8n was retired the matview
# went stale (data froze). We now keep it fresh in-process: a background loop
# refreshes it on an interval. A Postgres advisory lock makes this safe across
# uvicorn workers (only one worker refreshes per tick); the work runs in a
# thread so the async event loop never blocks on the ~9s REFRESH.
_DATABASE_URL = os.environ["DATABASE_URL"]
_REFRESH_INTERVAL_S = int(os.getenv("VTRIPS_REFRESH_INTERVAL_S", "300"))
_REFRESH_LOCK_KEY = 920_145 # arbitrary, stable advisory-lock key for this job
def _refresh_v_trips_once() -> str:
"""Refresh reporting.v_trips. Blocking — call via asyncio.to_thread.
Uses a dedicated autocommit connection: REFRESH ... CONCURRENTLY cannot run
inside a transaction block (so the pooled get_conn, which wraps a txn, won't
do). DATABASE_URL connects as a superuser, which may REFRESH the matview
even though reporting_refresher owns it.
"""
conn = psycopg2.connect(_DATABASE_URL, connect_timeout=10)
try:
conn.autocommit = True
with conn.cursor() as cur:
cur.execute("SELECT pg_try_advisory_lock(%s)", (_REFRESH_LOCK_KEY,))
if not cur.fetchone()[0]:
return "skipped (another worker holds the lock)"
try:
t0 = time.monotonic()
cur.execute("REFRESH MATERIALIZED VIEW CONCURRENTLY reporting.v_trips")
dur_ms = int((time.monotonic() - t0) * 1000)
cur.execute(
"INSERT INTO reporting.refresh_log"
"(refreshed_at, source, duration_ms, row_count, notes) "
"VALUES (now(), 'dashboard_api', %s,"
" (SELECT count(*) FROM reporting.v_trips), 'scheduled')",
(dur_ms,),
)
return f"refreshed in {dur_ms}ms"
finally:
cur.execute("SELECT pg_advisory_unlock(%s)", (_REFRESH_LOCK_KEY,))
finally:
conn.close()
async def _refresh_loop():
# Brief startup delay so the first refresh doesn't race container init.
await asyncio.sleep(15)
while True:
try:
result = await asyncio.to_thread(_refresh_v_trips_once)
log.info("v_trips refresh: %s", result)
except Exception:
log.exception("v_trips refresh failed (will retry next interval)")
await asyncio.sleep(_REFRESH_INTERVAL_S)
@asynccontextmanager
async def lifespan(app: FastAPI):
log.info(
"Dashboard API starting (v1.1). Origins=%s. v_trips refresh every %ss.",
_ALLOWED_ORIGINS, _REFRESH_INTERVAL_S,
)
refresher = asyncio.create_task(_refresh_loop())
yield
refresher.cancel()
try:
await refresher
except asyncio.CancelledError:
pass
close_pool()
app = FastAPI(title="Fireside Map Dashboard API", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=_ALLOWED_ORIGINS,
allow_methods=["GET", "POST", "OPTIONS"],
allow_headers=["*"],
)
_EMPTY_GEOJSON = {"type": "FeatureCollection", "features": []}
def _clean(v):
"""Treat missing / blank / sentinel values as None (= SQL wildcard)."""
if v is None:
return None
s = str(v).strip()
return s if s and s.lower() not in ("null", "undefined") else None
# ── Health ────────────────────────────────────────────────────────────────────
@app.get("/health")
def health():
return {"status": "ok"}
# ── Live positions (#004) ───────────────────────────────────────────────────
@app.get("/webhook/live-positions")
def live_positions(cost_centre: str | None = None, acc_status: str | None = None):
try:
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(
"SELECT reporting.fn_live_positions(%s, %s)",
(_clean(cost_centre), _clean(acc_status)),
)
payload = cur.fetchone()[0] or {}
return JSONResponse(
{
"summary": payload.get("summary") or {},
"geojson": payload.get("geojson") or _EMPTY_GEOJSON,
}
)
except Exception:
log.exception("live-positions failed")
return JSONResponse(
{
"error": {
"type": "unknown",
"message": "Live-position feed is unavailable. Try again in a few seconds.",
}
}
)
# `/webhook/live-positions/track` is the path the Live Positions SPA actually
# calls; `/webhook/vehicle-track` is kept as an alias. Both hit the same handler
# so the only frontend change is the base URL (N8N_BASE).
@app.get("/webhook/live-positions/track")
@app.get("/webhook/vehicle-track")
def vehicle_track(vehicle_number: str | None = None, hours: int = 1):
veh = _clean(vehicle_number)
if not veh:
return JSONResponse({"error": "vehicle_number is required"})
hours = max(1, min(24, hours or 1))
try:
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(
"SELECT reporting.fn_vehicle_track(%s, %s::int)", (veh, hours)
)
feature = cur.fetchone()[0]
return JSONResponse(
feature
or {"type": "Feature", "geometry": {"type": "LineString", "coordinates": []}, "properties": {}}
)
except Exception:
log.exception("vehicle-track failed for %s", veh)
return JSONResponse({"error": "vehicle-track unavailable"})
# ── Fleet trips (#002) ───────────────────────────────────────────────────────
_FILTER_OPTIONS_SQL = """
SELECT
(SELECT array_agg(driver ORDER BY driver) FROM reporting.v_filter_drivers) AS drivers,
(SELECT array_agg(cost_centre ORDER BY cost_centre) FROM reporting.v_filter_cost_centres) AS cost_centres,
(SELECT array_agg(assigned_city ORDER BY assigned_city) FROM reporting.v_filter_cities) AS cities,
(SELECT jsonb_agg(jsonb_build_object(
'vehicle_number', vehicle_number, 'drivers', drivers,
'cost_centre', cost_centre, 'assigned_city', assigned_city)
ORDER BY vehicle_number) FROM reporting.v_filter_vehicles) AS vehicles
"""
@app.get("/webhook/fleet-dashboard")
def fleet_filter_options():
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
cur.execute(_FILTER_OPTIONS_SQL)
row = cur.fetchone() or {}
return JSONResponse(
{
"drivers": row.get("drivers") or [],
"cost_centres": row.get("cost_centres") or [],
"cities": row.get("cities") or [],
"vehicles": row.get("vehicles") or [],
}
)
except Exception:
log.exception("fleet-dashboard filter options failed")
return JSONResponse({"drivers": [], "cost_centres": [], "cities": [], "vehicles": []})
def _preset_to_range(period: str | None, start_date, end_date):
"""Mirror of the n8n preset_to_range node."""
today = datetime.now(timezone.utc).date()
p = (period or "").strip()
if p == "today":
return today, today
if p == "30d":
return today - timedelta(days=29), today
if p == "custom":
def _d(v, default):
v = _clean(v)
if not v:
return default
try:
return date.fromisoformat(v)
except ValueError:
return default
return _d(start_date, today), _d(end_date, today)
# default + '7d'
return today - timedelta(days=6), today
@app.post("/webhook/fleet-dashboard")
async def fleet_trips(request: Request):
# The dashboard SPA posts application/x-www-form-urlencoded (not JSON), so
# parse by content-type. Reading the raw body + parse_qs avoids pulling in
# python-multipart. JSON is still accepted defensively (n8n-compat callers).
body: dict = {}
ctype = request.headers.get("content-type", "").lower()
try:
raw = await request.body()
if "application/json" in ctype:
parsed = json.loads(raw or b"{}")
body = parsed if isinstance(parsed, dict) else {}
else:
# x-www-form-urlencoded — parse_qs yields lists; keep the last value.
body = {k: v[-1] for k, v in parse_qs(raw.decode("utf-8", "replace")).items()}
except Exception:
body = {}
if isinstance(body.get("body"), dict):
body = body["body"]
start, end = _preset_to_range(
body.get("period"), body.get("start_date"), body.get("end_date")
)
veh = _clean(body.get("vehicle_numbers")) # comma-separated string or None
try:
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(
"""
SELECT reporting.fn_trips_for_map(
CASE WHEN %(veh)s IS NULL THEN NULL
ELSE string_to_array(%(veh)s, ',') END,
%(driver)s, %(cc)s, %(city)s, %(start)s::date, %(end)s::date
)
""",
{
"veh": veh,
"driver": _clean(body.get("driver")),
"cc": _clean(body.get("cost_centre")),
"city": _clean(body.get("assigned_city")),
"start": start,
"end": end,
},
)
payload = cur.fetchone()[0]
return JSONResponse(payload if payload is not None else {})
except Exception:
log.exception("fleet-dashboard trips failed")
return JSONResponse(
{"error": {"type": "unknown", "message": "Fleet feed is unavailable. Try again in a few seconds."}}
)

View file

@ -1,163 +0,0 @@
imei,device_name,mc_type,mc_type_use_scope,vehicle_name,vehicle_number,vehicle_models,vehicle_icon,vin,engine_number,vehicle_brand,fuel_100km,driver_name,driver_phone,sim,iccid,imsi,account,customer_name,device_group_id,device_group,activation_time,expiration,enabled_flag,status,city,current_mileage_km,created_at,updated_at,last_synced_at,vehicle_category,cost_centre,assigned_route,depot_geom,depot_address,assigned_city
353549090553685,Daniel Omondi - KMFF 099Z,AT4,personal,KMFF 099Z,KMFF 099Z,Motorbike,mtc,NULL,NULL,NULL,NULL,Robert,112794067,759336150,89254021334258404099,639021335840409,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-09-23 05:50:30+00,2040-09-23 23:59:59+00,1,1,mombasa,2354.7,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp patrol,NULL,NULL,NULL,mombasa
353549090561720,Wireless_Git,AT4,personal,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,701211913,89254021374215155053,639021371515505,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2025-06-09 09:12:50+00,2035-06-09 23:59:59+00,1,1,mombasa,5992.43,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,regional,NULL,NULL,NULL,mombasa
353549090566281,KDR 592N,AT4,personal,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,797680464,89254021334258159693,639021335815969,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2024-11-08 04:01:30+00,2034-11-08 23:59:59+00,1,1,nairobi,7771.9,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
353549090566885,Wireless GPS,AT4,personal,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,768445963,89254021334212352574,639021331235257,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2024-10-15 13:16:57+00,2034-10-15 23:59:59+00,1,1,nairobi,17036.41,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,nairobi
353549090567685,Daniel Kipkirui - KMFF 162Z,AT4,personal,KMFF 162Z,KMFF 162Z,Motorbike,mtc,NULL,NULL,NULL,NULL,Daniel Kipkirui,112795498,742532058,89254021264260388966,639021266038896,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-09-23 05:09:39+00,2040-09-23 23:59:59+00,1,1,mombasa,462.33,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp patrol,NULL,NULL,NULL,mombasa
353549090567701,Wireless,AT4,personal,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,790176094,89254021394215205906,639021391520590,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2024-11-08 04:04:44+00,2034-11-08 23:59:59+00,1,1,nairobi,16896.2,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,nairobi
359857081885410,Allan Owana - KDK 780K,GT06E,automobile,KDK 780K,KDK 780K,Probox,automobile,NULL,NULL,NULL,NULL,Allan Owana,NULL,703616117,89254021234222499854,639021232249985,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-19 09:32:22+00,2039-06-19 23:59:59+00,1,1,nairobi,128853.11,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857081886467,Gideon Kiprono - KCQ 215F,GT06E,automobile,KCQ 215F,OHS,Probox,automobile,NULL,NULL,NULL,0,Gideon Kiprono,NULL,746763076,89254021084186499865,639021088649986,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2019-06-30 09:30:00+00,2039-06-30 23:59:59+00,1,1,mombasa,141057.46,2026-04-23 10:56:37.983314+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857081886871,Kamonde KBA 467S,GT06E,automobile,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,746763083,89254021084186499873,639021088649987,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-30 09:09:14+00,2039-06-30 23:59:59+00,1,1,nairobi,74183.36,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,personal,NULL,NULL,NULL,nairobi
359857081886905,Kennedy Chege - KCQ 618K,GT06E,automobile,KCQ 618K,KCQ 618K,Probox,automobile,NULL,NULL,NULL,NULL,Kennedy Chege,NULL,746763132,89254021084186499923,639021088649992,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2019-06-30 07:08:35+00,2039-06-30 23:59:59+00,1,1,mombasa,215608.19,2026-04-23 10:35:37.678371+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857081887069,Wright Oseko - KCG 668W,GT06E,automobile,KCG 668W,KCG 668W,Probox,automobile,NULL,NULL,NULL,NULL,Wright Oseko,NULL,746763106,89254021084186499915,639021088649991,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2019-06-30 06:17:43+00,2039-06-30 23:59:59+00,1,1,nairobi,239001.19,2026-04-23 11:00:08.769463+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857081887192,Ndegwa Dancun - KCG 669W,GT06E,automobile,KCG 669W,KCG 669W,Probox,automobile,NULL,NULL,NULL,NULL,Ndegwa Dancun,NULL,746760191,89254021084186499501,639021088649950,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2019-06-15 10:26:15+00,2039-06-15 23:59:59+00,1,1,mombasa,199191.85,2026-04-23 10:34:29.074112+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857081891566,Simon Kamau - KCE 090R,GT06E,automobile,KCE 090R,KCE 090R,Probox,automobile,NULL,NULL,NULL,NULL,Simon Kamau,NULL,746760404,89254021084186499527,639021088649952,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2019-06-16 07:06:15+00,2039-06-16 23:59:59+00,1,1,nairobi,215592.36,2026-04-23 10:30:55.739184+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857081891590,Garage - KCE 699F,GT06E,automobile,KCE 699F,KCE 699F,Probox,automobile,NULL,NULL,NULL,NULL,Garage,NULL,746760215,89254021084186499519,639021088649951,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2019-06-16 11:11:24+00,2039-06-16 23:59:59+00,1,1,nairobi,207814.05,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857081891632,Samuel Kamau - KCA 542Q,GT06E,automobile,KCA 542Q,KCA 542Q,Probox,automobile,NULL,NULL,NULL,NULL,John Ondego,NULL,746760038,89254021084186499485,639021088649948,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-15 09:17:53+00,2039-06-15 23:59:59+00,1,1,nairobi,178914.47,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
359857081891798,Garage - KCH 167M,GT06E,automobile,KCH 167M,KCH 167M,Probox,automobile,NULL,NULL,NULL,NULL,Garage,NULL,746760102,89254021084186499493,639021088649949,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-16 10:18:57+00,2039-06-16 23:59:59+00,1,1,nairobi,168840.95,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857081892101,Cornelius Kimutai - KCU 938R,GT06E,automobile,KCU 938R,KCU 938R,Van,automobile,NULL,NULL,NULL,NULL,Cornelius Kimutai,NULL,746759919,89254021084186499451,639021088649945,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2019-06-12 08:13:48+00,2039-06-12 23:59:59+00,1,1,nairobi,149558.5,2026-04-23 10:29:21.507861+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
359857081892309,Nicholas Erastus - KCQ 581M,GT06E,automobile,KCQ 581M,KCQ 581M,Probox,automobile,NULL,NULL,NULL,NULL,Nicholas Erastus,NULL,700023776,89254021084178504672,639021087850467,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2019-06-09 09:39:40+00,2039-06-09 23:59:59+00,1,1,nairobi,209105.89,2026-04-23 10:40:40.169684+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857081892440,KAZ 489Z,GT06E,automobile,NULL,NULL,NULL,bus,NULL,NULL,NULL,NULL,NULL,NULL,700023806,89254021084178504698,639021087850469,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-09 10:04:39+00,2039-06-09 23:59:59+00,1,1,nairobi,38197.2,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,personal,NULL,NULL,NULL,nairobi
359857081892762,Nicholas,GT06E,automobile,NULL,NULL,Station Wagon,bus,NULL,NULL,Toyota,NULL,NULL,NULL,746760503,89254021274233125361,639021273312536,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2019-06-16 08:31:46+00,2039-06-16 23:59:59+00,1,1,mombasa,51048.97,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,personal,NULL,NULL,NULL,nairobi
359857082037185,Amani Kazungu - KCY 084X,GT06E,automobile,KCY 084X,KCY 084X,Probox,automobile,NULL,NULL,NULL,NULL,Amani Kazungu,NULL,757338522,89254021154287000597,639021158700059,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-07-13 09:42:28+00,2040-07-13 23:59:59+00,1,1,mombasa,172298.81,2026-04-23 10:51:08.665273+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
359857082038977,Wilfred Kinyanjui - KCU 729C,GT06E,automobile,KCU 729C,KCU 729C,Crane,truck,NULL,NULL,NULL,NULL,Wilfred Kinyanjui,NULL,110094469,89254021164215938057,639021161593805,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-04-05 09:26:00+00,2040-04-05 23:59:59+00,1,1,nairobi,172487.09,2026-04-23 10:24:33.914628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,mombasa
359857082040981,Amani Sulubu - KCY 090X,GT06E,automobile,KCY 090X,KCY 090X,Probox,automobile,NULL,NULL,NULL,NULL,Amani Sulubu,NULL,793375853,89254021064168004164,639021066800416,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-07-13 07:25:16+00,2040-07-13 23:59:59+00,1,1,mombasa,166028.15,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082042052,Gabriel Musumba - KCE 690F,GT06E,automobile,KCE 690F,KCE 690F,Probox,automobile,NULL,NULL,NULL,NULL,Gabriel Musumba,NULL,110094466,89254021164215938024,639021161593802,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2020-04-03 17:30:13+00,2040-04-03 23:59:59+00,1,1,nairobi,192693.23,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857082042854,Elias Baya - KCZ 476E,GT06E,automobile,KCZ 476E,KCZ 476E,Probox,automobile,NULL,NULL,NULL,NULL,Elias Baya,NULL,110941187,89254021164224352993,639021162435299,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-08-09 05:06:42+00,2040-08-09 23:59:59+00,1,1,mombasa,217595.68,2026-04-23 10:33:56.216621+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
359857082042953,KCU 865Q Vanguard,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,null,NULL,2026-04-23 13:24:33.293453+00,2026-04-23 13:24:33.293453+00,NULL,NULL,null,NULL,NULL,NULL,null
359857082044280,Lawrence Kijogi - KCY 080X,GT06E,automobile,KCY 080X,KCY 080X,Probox,automobile,NULL,NULL,NULL,NULL,Lawrence Kijogi,NULL,708155933,89254029851005131222,639029850513122,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-07-13 11:05:02+00,2040-07-13 11:05:02+00,1,1,mombasa,169740.37,2026-04-23 14:52:58.983571+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,mombasa
359857082046145,Joseph Kabandi - KCY 076X,GT06E,automobile,KCY 076X,KCY 076X,Probox,automobile,NULL,NULL,NULL,NULL,Joseph Kabandi,NULL,110850007,89254021164223447158,639021162344715,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-07-13 08:31:26+00,2040-07-13 23:59:59+00,1,1,mombasa,122254.48,2026-04-23 10:47:40.895504+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082896911,Hamisi Pande - KDD 689Y,GT06E,automobile,KDD 689Y,KDD 689Y,Probox,automobile,NULL,NULL,NULL,NULL,Hamisi Pande,NULL,112714612,89254021214211314660,639021211131466,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-09-17 11:50:53+00,2041-09-17 23:59:59+00,1,1,nairobi,163435.74,2026-04-23 10:26:09.922447+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082897091,Peter Mbugua - KDK 728K,GT06E,automobile,KDK 728K,KDK 728K,Probox,automobile,NULL,NULL,NULL,NULL,Peter Mbugua,NULL,790262984,89254021234222500396,639021232250039,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-12-14 11:31:57+00,2042-12-14 23:59:59+00,1,1,nairobi,131109.26,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082897257,Cassius Wakiyo - KDB 323M,GT06E,automobile,KDB 323M,KDB 323M,Probox,automobile,NULL,NULL,NULL,NULL,Cassius Wakiyo,NULL,746428882,89254021234222500818,639021232250081,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-08-29 15:07:26+00,2041-08-29 15:07:26+00,1,1,nairobi,121688.92,2026-04-23 10:28:26.388654+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857082897737,John Makori - KDB 585E,GT06E,automobile,KDB 585E,KDB 585E,Probox,automobile,NULL,NULL,NULL,NULL,John Makori,NULL,114596734,89254021214211145262,639021211114526,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-08-29 14:29:28+00,2041-08-29 14:29:28+00,1,1,nairobi,156765.03,2026-04-23 10:38:57.445964+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,planning,NULL,NULL,NULL,nairobi
359857082897794,Mutuku Joseph - KDC 739F,GT06E,automobile,KDC 739F,KDC 739F,Probox,automobile,NULL,NULL,NULL,NULL,Mutuku Joseph,115019037,115019037,89254021224222632356,639021222263235,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-04-10 14:55:32+00,2041-04-10 14:55:32+00,1,1,nairobi,205169.79,2026-04-23 10:30:22.530563+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
359857082898008,Samuel Ng'ang'a - KDE 264M,GT06E,automobile,KDE 264M,KDE 264M,Probox,automobile,NULL,NULL,NULL,NULL,Samuel Ng'ang'a,NULL,711731539,89254021264260342245,639021266034224,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-10-28 09:43:11+00,2041-10-28 23:59:59+00,1,1,nairobi,126584.24,2026-04-23 11:35:59.816581+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082898016,Job Ngare - KDM 309S,GT06E,automobile,KDM 309S,KDM 309S,Probox,automobile,NULL,NULL,NULL,NULL,Job Ngare,NULL,706895756,89254021324273007563,639021327300756,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-08-15 13:45:26+00,2033-08-15 23:59:59+00,1,1,mombasa,107726.56,2026-04-23 11:20:25.939244+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082898073,Mutuku Antony - KDK 732K,GT06E,automobile,KDK 732K,KDK 732K,Probox,automobile,NULL,NULL,NULL,NULL,Mutuku Antony,NULL,793026954,89254021234222387539,639021232238753,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-12-20 06:33:12+00,2042-12-20 23:59:59+00,1,1,mombasa,82096.79,2026-04-23 14:52:07.094447+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
359857082898487,Dan Watila - KDE 638J,GT06E,automobile,KDE 638J,KDE 638J,Probox,automobile,NULL,NULL,NULL,NULL,Dan Watila,NULL,116242996,89254021334258404214,639021335840421,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-10-21 15:50:06+00,2041-10-21 23:59:59+00,1,1,nairobi,123872.36,2026-04-23 10:31:45.186653+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082900168,KDD 913G_Ruth Mazda,NULL,NULL,KDD 913G,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,nairobi,NULL,2026-04-23 15:09:48.575568+00,2026-04-23 15:09:48.575568+00,NULL,NULL,personal,NULL,NULL,NULL,nairobi
359857082900341,Simon Munda - KCZ 154S,GT06E,automobile,KCZ 154S,KCZ 154S,Probox,automobile,NULL,NULL,NULL,NULL,Simon Munda,NULL,757236135,89254021154296723312,639021159672331,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-09-23 17:12:51+00,2040-09-23 23:59:59+00,1,1,mombasa,186504.1,2026-04-23 10:45:21.454595+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082900358,Geoffrey Too - KDM 308S,GT06E,automobile,KDM 308S,KDM 308S,Probox,automobile,NULL,NULL,NULL,NULL,Geoffrey Too,NULL,796527601,89254021264260126572,639021266012657,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-10-21 15:25:28+00,2041-10-21 23:59:59+00,1,1,nairobi,142216.91,2026-04-23 12:35:06.661934+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857082900697,George Ochieng' - KDD 684Y,GT06E,automobile,KDD 684Y,KDD 684Y,Probox,automobile,NULL,NULL,NULL,NULL,George Ochieng',NULL,114879518,89254021214211314678,639021211131467,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-09-17 10:53:11+00,2041-09-17 23:59:59+00,1,1,nairobi,152820.07,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857082902461,Sadique Wakayula - KDC 490Q,GT06E,automobile,KDC 490Q,KDC 490Q,Crane,truck,NULL,NULL,NULL,NULL,Sadique Wakayula,NULL,757556468,89254021154296722488,639021159672248,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-05-22 11:27:30+00,2041-05-22 11:27:30+00,1,1,mombasa,183009.52,2026-04-23 11:16:03.730519+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,mombasa
359857082902503,Felix Andole - KDC 207R,GT06E,automobile,KDC 207R,KDC 207R,Probox,automobile,NULL,NULL,NULL,NULL,Felix Andole,NULL,794820817,89254021224270993254,639021227099325,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-05-15 11:38:24+00,2041-05-15 11:38:24+00,1,1,mombasa,208724.46,2026-04-23 15:32:46.935568+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082907973,Felix Muema - KCZ 223P,GT06E,automobile,KCZ 223P,KCZ 223P,Probox,automobile,NULL,NULL,NULL,NULL,Felix Muema,NULL,757843826,89254021154287138371,639021158713837,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-08-22 14:01:25+00,2040-08-22 23:59:59+00,1,1,mombasa,222126.36,2026-04-23 10:26:48.220151+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857082908500,Santoes Omondi - KCZ 181P,GT06E,automobile,KCZ 181P,KCZ 181P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Santoes Omondi,NULL,701211974,89254021374215155087,639021371515508,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-08-23 08:58:55+00,2040-08-23 23:59:59+00,1,1,mombasa,221339.62,2026-04-23 10:48:09.537346+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857082910589,Patric Bett - KDA 609E,GT06E,automobile,KDA 609E,KDA 609E,Probox,automobile,NULL,NULL,NULL,NULL,Patric Bett,NULL,797622637,89254021154296722496,639021159672249,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2020-10-26 15:46:41+00,2040-10-26 23:59:59+00,1,1,nairobi,194618.69,2026-04-23 10:34:25.350862+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
359857082910886,Makanda Andrew - KCZ 155P,GT06E,automobile,KCZ 155P,KCZ 155P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Makanda Andrew,NULL,745067338,89254021154287138397,639021158713839,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-08-23 11:52:35+00,2040-08-23 23:59:59+00,1,1,mombasa,231065.89,2026-04-23 11:36:31.150282+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857082911983,Brian Ngetich - KDA 717B,GT06E,automobile,KDA 717B,KDA 717B,Probox,automobile,NULL,NULL,NULL,NULL,Brian Ngetich,795188807,795188807,89254021214211145288,639021211114528,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-08-29 07:21:43+00,2041-08-29 07:21:43+00,1,1,nairobi,145404.96,2026-04-23 10:36:11.774166+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082912239,Dickson Jaoko - KDK 815R,GT06E,automobile,KDK 815R,KDK 815R,Probox,automobile,NULL,NULL,Probox,0,Sammy,NULL,706392117,89254021234296021287,639021239602128,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-06-21 07:14:51+00,2033-06-21 23:59:59+00,1,1,voi,77008.75,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857082912486,Moses Wambua - KCZ 751V,GT06E,automobile,KCZ 751V,KCZ 751V,Probox,automobile,NULL,NULL,NULL,NULL,Moses Wambua,792756503,792756503,89254021154296723437,639021159672343,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-09-23 10:14:28+00,2040-09-23 23:59:59+00,1,1,mombasa,139762.2,2026-04-23 10:41:00.207177+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
359857082916826,Denis Kazungu - KDM 794R,GT06E,automobile,KDM 794R,KDM 794R,Probox,automobile,NULL,NULL,NULL,NULL,Denis Kazungu,NULL,705700971,89254021324273006854,639021327300685,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2023-08-21 06:38:00+00,2033-08-21 23:59:59+00,1,1,mombasa,79639.71,2026-04-23 20:18:46.496567+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
359857082918012,Charles Nyambane - KCB 711C,GT06E,automobile,KCB 711C,KCB 711C,Probox,automobile,NULL,NULL,NULL,NULL,Charles Nyambane,NULL,793704231,89254021154287138363,639021158713836,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2020-09-21 10:48:35+00,2040-09-21 23:59:59+00,1,1,nairobi,159597.27,2026-04-23 10:25:52.843474+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
359857082918038,Mbuvi Kioko - KCC 199P,GT06E,automobile,KCC 199P,KCC 199P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Mbuvi Kioko,NULL,797318126,89254021154287138389,639021158713838,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-08-22 15:26:27+00,2040-08-22 23:59:59+00,1,1,mombasa,222106.8,2026-04-23 12:09:05.609075+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
359857082918186,KDD 977T Fielder,NULL,NULL,KDD 977T,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,null,NULL,2026-04-23 10:36:25.832836+00,2026-04-23 10:36:25.832836+00,NULL,NULL,null,NULL,NULL,NULL,null
359857082925330,Noel Merengeni - KCY 838X,GT06E,automobile,KCY 838X,KCY 838X,Probox,automobile,NULL,NULL,NULL,NULL,Noel Merengeni,NULL,794873610,89254021154296723429,639021159672342,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2020-10-26 16:36:37+00,2040-10-26 23:59:59+00,1,1,voi,194429.24,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050288212,Nicholas Erastus - KCQ 581M,JC400P,automobile,KCQ 581M,KCQ 581M,Probox,automobile,NULL,NULL,NULL,NULL,Nicholas Erastus,NULL,746979531,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-11-02 09:07:41+00,2041-11-02 23:59:59+00,1,1,nairobi,40898.98,2026-04-23 13:05:18.326254+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050288261,Patric Bett - KDA 609E,JC400P,automobile,KDA 609E,KDA 609E,Probox,automobile,NULL,NULL,NULL,NULL,Patric Bett,112693340,790176509,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2021-10-23 11:50:11+00,2041-10-23 23:59:59+00,1,1,nairobi,18538.42,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050288303,Elias Baya - KCZ 476E,JC400P,automobile,KCZ 476E,KCZ 476E,Probox,automobile,NULL,NULL,NULL,NULL,Elias Baya,NULL,115870439,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-11-06 08:50:28+00,2041-11-06 23:59:59+00,1,1,mombasa,116091.42,2026-04-23 17:46:09.993791+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050288345,Santoes Omondi - KCZ 181P,JC400P,automobile,KCZ 181P,KCZ 181P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Santoes Omondi,NULL,768446105,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2021-11-06 10:17:51+00,2041-11-06 23:59:59+00,1,1,mombasa,107462.79,2026-04-23 10:29:45.563231+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050288360,Brian Ngetich - KDA 717B,JC400P,automobile,KDA 717B,KDA 717B,Probox,automobile,NULL,NULL,NULL,NULL,Brian Ngetich,NULL,717867861,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2021-11-05 08:47:08+00,2041-11-05 23:59:59+00,1,1,nairobi,17808.56,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050521521,John Kimeria - KDS 525D,JC400P,automobile,KDS 525D,KDS 525D,Crane,truck,NULL,NULL,NULL,NULL,John Kimeria,NULL,752958416,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-11-26 07:58:13+00,2033-11-26 23:59:59+00,1,1,nairobi,19354.92,2026-04-23 10:28:34.917147+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
862798050521612,Denis Kazungu - KDM 794R,JC400P,automobile,KDM 794R,KDM 794R,Probox,automobile,NULL,NULL,NULL,NULL,Denis Kazungu,NULL,704113731,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-22 07:52:12+00,2042-01-22 23:59:59+00,1,1,mombasa,4350.75,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050521752,Simon Munda - KCZ 154S,JC400P,automobile,KCZ 154S,KCZ 154S,Probox,automobile,NULL,NULL,NULL,NULL,Simon Munda,NULL,113805921,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 08:14:37+00,2042-01-16 23:59:59+00,1,1,mombasa,4698.02,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050522065,Gideon Kiprono - KCQ 215F,JC400P,automobile,KCQ 215F,KCQ 215F,Probox,automobile,NULL,NULL,NULL,NULL,Gideon Kiprono,NULL,113343715,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2022-01-16 07:10:16+00,2042-01-16 23:59:59+00,1,1,mombasa,8111.98,2026-04-23 18:23:51.445608+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050522107,Cassius Wakiyo - KDB 323M,JC400P,automobile,KDB 323M,KDB 323M,Probox,automobile,NULL,NULL,NULL,NULL,Cassius Wakiyo,NULL,114149576,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 08:18:15+00,2042-01-22 23:59:59+00,1,1,nairobi,23316.09,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050522719,Mbuvi Kioko - KCZ 199P,JC400P,automobile,KCZ 199P,KCZ 199P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Mbuvi Kioko,NULL,768218655,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 22:07:24+00,2042-01-16 23:59:59+00,1,1,voi,16973.89,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050522743,Charles Nyambane - KCB 711C,JC400P,automobile,KCB 711C,KCB 711C,Probox,automobile,NULL,NULL,NULL,NULL,Charles Nyambane,NULL,768657106,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-12-22 21:53:57+00,2033-12-22 23:59:59+00,1,1,nairobi,12133.75,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050522859,Garage - KCH 167M,JC400P,automobile,KCH 167M,KCH 167M,Probox,automobile,NULL,NULL,NULL,NULL,Garage,NULL,706740252,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 08:23:21+00,2042-01-15 23:59:59+00,1,1,nairobi,6934.86,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050522883,Dan Watila - KDE 638J,JC400P,automobile,KDE 638J,KDE 638J,Probox,automobile,NULL,NULL,NULL,NULL,Dan Watila,NULL,112615393,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 07:17:21+00,2042-01-15 23:59:59+00,1,1,nairobi,14483.01,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050522891,Lawrence Kijogi - KCY 080X,JC400P,automobile,KCY 080X,KCY 080X,Pick-Up,automobile,NULL,NULL,NULL,NULL,Lawrence Kijogi,NULL,113287191,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 10:51:30+00,2042-01-16 23:59:59+00,1,1,mombasa,11585.33,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,mombasa
862798050523014,Samuel Muriithy - KDR 594N,JC400P,automobile,KDR 594N,KDR 594N,Probox,automobile,NULL,NULL,NULL,NULL,Samuel Muriithy,NULL,790175423,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-21 15:54:32+00,2033-12-21 23:59:59+00,1,1,nairobi,27275.43,2026-04-23 10:26:17.747928+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
862798050523063,Kelvin Wambugu - KDR 594N,JC400P,automobile,KDR 594N,KDR 594N,Probox,automobile,NULL,NULL,NULL,NULL,Kelvin Wambugu,NULL,701211876,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 19:24:51+00,2043-12-22 19:24:51+00,1,1,nairobi,32698.94,2026-04-23 15:31:08.065856+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
862798050523139,Mike Wanaswa - KDT 724R,JC400P,automobile,KDT 724R,KDT 724R,Probox,automobile,NULL,NULL,NULL,NULL,Mike Wanaswa,NULL,790175045,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 22:28:09+00,2043-12-22 22:28:09+00,1,1,mombasa,29559.82,2026-04-23 11:16:37.277518+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050523204,Amani Kazungu - KCY 084X,JC400P,automobile,KCY 084X,KCY 084X,Probox,automobile,NULL,NULL,NULL,NULL,Amani Kazungu,NULL,707892547,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 06:18:20+00,2042-01-16 23:59:59+00,1,1,mombasa,66955.7,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050523295,Emmanuel Luseno - KDS 453 Y,JC400P,automobile,KDS 453 Y,KDS 453 Y,Pick-Up,automobile,NULL,NULL,NULL,NULL,Emmanuel Luseno,NULL,700242474,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 14:39:50+00,2033-12-22 23:59:59+00,1,1,nairobi,37098.35,2026-04-23 11:29:48.369147+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
862798050523337,Victor Kimutai - KDS 919Y,JC400P,automobile,KDS 919Y,KDS 919Y,Probox,automobile,NULL,NULL,NULL,NULL,Victor Kimutai,NULL,700242527,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 18:00:49+00,2043-12-22 18:00:49+00,1,1,mombasa,50756.64,2026-04-23 10:27:13.522675+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050523386,George Ochieng' - KDD 684Y,JC400P,automobile,KDD 684Y,KDD 684Y,Probox,automobile,NULL,NULL,NULL,NULL,George Ochieng',NULL,785586834,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 06:36:08+00,2042-01-22 23:59:59+00,1,1,nairobi,33979.83,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050523527,Allan Owana - KDK 780K,JC400P,automobile,KDK 780K,KDK 780K,Probox,automobile,NULL,NULL,NULL,NULL,Allan Owana,NULL,792375024,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2022-12-03 10:43:41+00,2042-12-03 23:59:59+00,1,1,nairobi,109564.95,2026-04-23 10:25:24.360765+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050523618,Geoffrey Too - KDM 308S,JC400P,automobile,KDM 308S,KDM 308S,Probox,automobile,NULL,NULL,NULL,NULL,Geoffrey Too,NULL,701211625,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-08-15 15:42:32+00,2033-08-15 23:59:59+00,1,1,nairobi,26496.5,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050523626,Major Simiyu - KDS 949Y,JC400P,automobile,KDS 949Y,KDS 949Y,Probox,automobile,NULL,NULL,NULL,NULL,Major Simiyu,NULL,701211892,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 18:05:16+00,2033-12-22 23:59:59+00,1,1,mombasa,37042.97,2026-04-23 10:51:18.245194+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050523816,Job Ngare - KDM 309S,JC400P,automobile,KDM 309S,KDM 309S,Probox,automobile,NULL,NULL,NULL,NULL,Job Ngare,NULL,707936781,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-08-15 14:05:52+00,2033-08-15 23:59:59+00,1,1,mombasa,54320.21,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050523949,Joseph Kabandi - KCY 076X,JC400P,automobile,KCY 076X,KCY 076X,Probox,automobile,NULL,NULL,NULL,NULL,Joseph Kabandi,NULL,113288492,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 05:52:54+00,2042-01-16 23:59:59+00,1,1,mombasa,14427.5,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050524012,Moses Wambua - KCZ 751V,JC400P,automobile,KCZ 751V,KCZ 751V,Probox,automobile,NULL,NULL,NULL,NULL,Moses Wambua,NULL,113313797,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 07:40:10+00,2042-01-16 23:59:59+00,1,1,mombasa,26551.46,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050524087,Felix Muema - KCZ 223P,JC400P,automobile,KCZ 223P,KCZ 223P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Felix Muema,NULL,113973875,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 13:02:24+00,2042-01-16 23:59:59+00,1,1,mombasa,11543.26,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050524368,862798050524368,JC400P,automobile,NULL,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-10-29 09:24:53+00,2042-10-29 23:59:59+00,1,1,null,169208.91,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
862798050524384,Hamisi Pande - KDD 689Y,JC400P,automobile,KDD 689Y,KDD 689Y,Probox,automobile,NULL,NULL,NULL,0,Hamisi Pande,NULL,701211744,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 05:49:19+00,2042-01-22 23:59:59+00,1,1,nairobi,13685.18,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050524392,Ndegwa Dancun - KCG 669W,JC400P,automobile,KCG 669W,KCG 669W,Probox,automobile,NULL,NULL,NULL,NULL,Ndegwa Dancun,NULL,113799173,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 09:43:10+00,2042-01-16 23:59:59+00,1,1,mombasa,13638.25,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050524426,Amani Sulubu - KCY 090X,JC400P,automobile,KCY 090X,KCY 090X,Probox,automobile,NULL,NULL,NULL,NULL,Amani Sulubu,NULL,113823350,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2022-01-16 08:56:25+00,2042-01-16 23:59:59+00,1,1,mombasa,14243.83,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050524533,Leonard Nzai - KDM 306S,JC400P,automobile,KDM 306S,KDM 306S,Probox,automobile,NULL,NULL,NULL,NULL,Leonard Nzai,NULL,703487162,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-08-21 08:22:12+00,2033-08-21 23:59:59+00,1,1,mombasa,68942.41,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050524558,Mutuku Joseph - KDC 739F,JC400P,automobile,KDC 739F,KDC 739F,Probox,automobile,NULL,NULL,NULL,NULL,Mutuku Joseph,NULL,100858817,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 10:38:25+00,2042-01-22 23:59:59+00,1,1,nairobi,23711.63,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
862798050524566,Makanda Andrew - KCZ 155P,JC400P,automobile,KCZ 155P,KCZ 155P,Pick-Up,automobile,NULL,NULL,NULL,NULL,Makanda Andrew,NULL,758781444,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-22 09:47:33+00,2042-01-22 23:59:59+00,1,1,mombasa,31663.3,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050524608,Peter Mbugua - KDK 728K,JC400P,automobile,KDK 728K,KDK 728K,Probox,automobile,NULL,NULL,NULL,NULL,Peter Mbugua,NULL,706742413,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-12-03 12:11:32+00,2042-12-03 23:59:59+00,1,1,nairobi,7219.31,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050524657,Felix Andole - KDC 207R,JC400P,automobile,KDC 207R,KDC 207R,Probox,automobile,NULL,NULL,NULL,NULL,Felix Andole,NULL,758689195,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 07:17:47+00,2042-01-22 23:59:59+00,1,1,mombasa,46233.99,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050524681,Mutuku Antony - KDK 732K,JC400P,automobile,KDK 732K,KDK 732K,Probox,automobile,NULL,NULL,NULL,NULL,Mutuku Antony,NULL,796275746,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-12-06 13:37:49+00,2042-12-06 23:59:59+00,1,1,mombasa,14993.36,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
862798050524707,Garage - KCE 699F,JC400P,automobile,KCE 699F,KCE 699F,Probox,automobile,NULL,NULL,NULL,NULL,Garage,NULL,110525751,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 07:58:49+00,2042-01-15 23:59:59+00,1,1,nairobi,34715.97,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
862798050524897,Cornelius Kimutai - KCU 938R,JC400P,automobile,KCU 938R,KCU 938R,Van,automobile,NULL,NULL,NULL,NULL,Cornelius Kimutai,NULL,114924404,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-22 09:03:40+00,2042-01-22 23:59:59+00,1,1,nairobi,12668.43,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
862798050525068,Samuel Ng'ang'a - KDE 264M,JC400P,automobile,KDE 264M,KDE 264M,Probox,automobile,NULL,NULL,NULL,NULL,Samuel Ng'ang'a,NULL,768658564,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-12-22 13:33:42+00,2033-12-22 23:59:59+00,1,1,nairobi,12299.13,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050525225,Sadique Wakayula - KDC 490Q,JC400P,automobile,KDC 490Q,KDC 490Q,Crane,truck,NULL,NULL,NULL,NULL,Sadique Wakayula,NULL,768652386,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-12-22 20:52:08+00,2043-12-22 20:52:08+00,1,1,mombasa,19138.05,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
862798050525266,Dickson Jaoko - KDK 815R,JC400P,automobile,KDK 815R,KDK 815R,Probox,automobile,NULL,NULL,NULL,NULL,Dickson Jaoko,NULL,706665867,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-06-21 07:50:00+00,2033-06-21 23:59:59+00,1,1,mombasa,63754.71,2026-04-23 13:50:24.21992+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050525423,Makori John - KDB 585E,JC400P,automobile,KDB 585E,KDB 585E,Probox,automobile,NULL,NULL,NULL,NULL,Makori John,NULL,701211724,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 10:59:19+00,2042-01-15 23:59:59+00,1,1,mombasa,48804.83,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,planning,NULL,NULL,NULL,mombasa
862798050525589,Simon Kamau - KCE 090R,JC400P,automobile,KCE 090R,KCE 090R,Probox,automobile,NULL,NULL,NULL,NULL,Simon Kamau,NULL,796276387,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-19 10:10:04+00,2042-01-19 23:59:59+00,1,1,nairobi,15874.39,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050525605,Samuel Kamau - KCA 542Q,JC400P,automobile,KCA 542Q,KCA 542Q,Probox,automobile,NULL,NULL,NULL,NULL,John Ondego,NULL,110526783,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 05:56:11+00,2042-01-15 23:59:59+00,1,1,nairobi,23976.94,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
862798050525613,Kennedy Chege - KCQ 618K,JC400P,automobile,KCQ 618K,KCQ 618K,Probox,automobile,NULL,NULL,NULL,NULL,Kennedy Chege,NULL,729994247,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-16 05:21:05+00,2042-01-16 23:59:59+00,1,1,mombasa,12804.24,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
862798050525670,Gabriel Musumba - KCE 690F,JC400P,automobile,KCE 690F,KCE 690F,Probox,automobile,NULL,NULL,NULL,NULL,Gabriel Musumba,NULL,701211996,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2022-01-15 06:40:01+00,2042-01-15 23:59:59+00,1,1,nairobi,20110.93,2026-04-24 05:34:23.167312+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050525753,Noel Merengeni - KCY 838X,JC400P,automobile,KCY 838X,KCY 838X,Probox,automobile,NULL,NULL,NULL,NULL,Noel Merengeni,NULL,NULL,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2022-01-15 05:24:00+00,2042-01-15 23:59:59+00,1,1,voi,14596.59,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,voi
862798050525837,Kennedy Ondieki - KCU 237Z,JC400P,automobile,KCU 237Z,KCU 237Z,Probox,automobile,NULL,NULL,NULL,NULL,Kennedy Ondieki,NULL,113669852,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2023-12-21 19:32:44+00,2033-12-21 23:59:59+00,1,1,nairobi,NULL,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798050525951,Wright Oseko - KCG 668W,JC400P,automobile,KCG 668W,KCG 668W,Probox,automobile,NULL,NULL,NULL,NULL,Wright Oseko,NULL,741943212,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2022-01-15 09:36:45+00,2042-01-15 23:59:59+00,1,1,nairobi,13116,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798050526165,Wilfred Kinyanjui - KCU 729C,JC400P,automobile,KCU 729C,KCU 729C,Crane,truck,NULL,NULL,NULL,NULL,Wilfred Kinyanjui,NULL,790564929,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2023-11-26 10:17:19+00,2033-11-26 23:59:59+00,1,1,nairobi,24270.2,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
862798050526231,Rashid Hassan - KDM 840V,JC400P,automobile,KDM 840V,KDM 840V,Probox,automobile,NULL,NULL,NULL,NULL,Rashid Hassan,NULL,790175526,NULL,NULL,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2023-12-22 22:36:15+00,2043-12-22 22:36:15+00,1,1,mombasa,45418.38,2026-04-23 10:29:41.575467+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
862798050526256,Ian Dancun - KDT 923R,JC400P,automobile,KDT 923R,KDT 923R,Probox,automobile,NULL,NULL,NULL,NULL,Ian Dancun,NULL,794873610,NULL,NULL,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2023-12-22 19:37:24+00,2043-12-22 19:37:24+00,1,1,mombasa,11093.11,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,qehs,NULL,NULL,NULL,mombasa
862798052707888,Benjamin Ananda - KDV 438W,JC400P,automobile,KDV 438W,KDV 438W,Probox,automobile,NULL,NULL,NULL,NULL,Benjamin Ananda,NULL,758047312,89254021414206816980,639021410681698,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-12-15 07:39:23+00,2035-12-15 23:59:59+00,1,1,nairobi,8720.87,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,planning,NULL,NULL,NULL,nairobi
862798052707896,John Mbugua - KDW 573B,JC400P,automobile,KDW 573B,KDW 573B,Probox,automobile,NULL,NULL,NULL,NULL,John Mbugua,NULL,NULL,89254021414206816725,639021410681672,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-01-30 14:48:17+00,2036-01-30 23:59:59+00,1,1,nairobi,515.16,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798052707946,Tom Wekesa/OSP-KCY 930Y_CAM,JC400P,automobile,KCY 930Y,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,758047806,89254021414206816766,639021410681676,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2026-01-20 21:02:13+00,2036-01-20 23:59:59+00,1,1,nairobi,10079.17,2026-04-23 10:25:24.363965+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798052708035,862798052708035,JC400P,automobile,NULL,NULL,Probox,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,NULL,NULL,1,1,null,NULL,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
862798052708068,Dominic Wambua - KDV 683Z,JC400P,automobile,KDV 683Z,KDV 683Z,Probox,automobile,NULL,NULL,NULL,NULL,Dominic Wambua,NULL,758048043,89254021414206816964,639021410681696,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-01-24 09:20:09+00,2036-01-24 23:59:59+00,1,1,nairobi,4438.55,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
862798052708076,Albert Mutwiri - KDV 437W,JC400P,automobile,KDV 437W,KDV 437W,Probox,automobile,NULL,NULL,NULL,NULL,Albert Mutwiri,NULL,758047094,89254021414206816782,639021410681678,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-12-13 15:03:30+00,2035-12-13 23:59:59+00,1,1,nairobi,5575.64,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
862798052708167,Levine Wasike - KDV 439W,JC400P,automobile,KDV 439W,KDV 439W,Probox,automobile,NULL,NULL,NULL,NULL,Levine Wasike,NULL,758046738,89254021414206816741,639021410681674,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-12-13 19:49:29+00,2035-12-13 23:59:59+00,1,1,nairobi,4601.08,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798052708282,Godffrey Nandwa - KCN 496A,JC400P,automobile,KCN 496A,KCN 496A,Probox,automobile,NULL,NULL,NULL,NULL,Godffrey Nandwa,NULL,758047934,89254021414206816865,639021410681686,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2026-01-25 18:55:54+00,2036-01-25 23:59:59+00,1,1,nairobi,7040.6,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798052713654,Garage/ISP_KCL 502T_CAM,JC400P,automobile,KCL 502T,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,780215879,89254035061001753803,639035060175380,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-09-02 10:09:57+00,2035-09-02 23:59:59+00,1,1,nairobi,5199.72,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798052713696,862798052713696,JC400P,automobile,NULL,NULL,Probox,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,89254021394215205906,639021391520590,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-09-02 10:20:58+00,2035-09-02 23:59:59+00,1,1,null,6214.49,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
862798052713761,Management_Mazda - KDU 613A,JC400P,automobile,KDU 613A,KDU 613A,Mazda,automobile,NULL,NULL,NULL,NULL,Management_Mazda,NULL,790176786,89254021394215205955,639021391520595,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-07-09 15:49:26+00,2035-07-09 23:59:59+00,1,1,nairobi,9262.78,2026-04-23 16:40:48.879666+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,management,NULL,NULL,NULL,nairobi
862798052713779,Benard Kimutai - KDN 759G,JC400P,automobile,KDN 759G,KDN 759G,Probox,automobile,NULL,NULL,NULL,NULL,Benard Kimutai,NULL,752143258,89254035061001753860,639035060175386,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-08-23 11:15:59+00,2035-08-23 23:59:59+00,1,1,nairobi,5344.24,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
862798052713811,James Onyango - KDU 613B,JC400P,automobile,KDU 613B,KDU 613B,Probox,automobile,NULL,NULL,NULL,NULL,James Onyango,NULL,790176542,89254021394215205880,639021391520588,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-09 19:24:14+00,2035-07-09 23:59:59+00,1,1,nairobi,9657.42,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798052713837,Kennedy Ondieki - KCU 237Z,JC400P,automobile,KCU 237Z,KCU 237Z,Probox,automobile,NULL,NULL,NULL,NULL,Kennedy Ondieki,NULL,113669852,89254021414206327855,639021410632785,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-10-08 14:55:23+00,2035-10-08 23:59:59+00,1,1,nairobi,9346.02,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
862798052713985,Timothy Gitau - KDT 916R,JC400P,automobile,KDT 916R,KDT 916R,Probox,automobile,NULL,NULL,NULL,NULL,Timothy Gitau,NULL,768696668,89254021394274518892,639021397451889,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-08-02 18:21:23+00,2035-08-02 23:59:59+00,1,1,mombasa,19998.22,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,regional,NULL,NULL,NULL,mombasa
862798052714066,862798052714066,JC400P,automobile,NULL,NULL,Probox,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,89254021414206378684,639021410637868,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-11-21 17:44:44+00,2035-11-21 23:59:59+00,1,1,null,10755.28,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
862798052715220,Rofas Njagi - KDT 728R,JC400P,automobile,KDT 728R,KDT 728R,Probox,automobile,NULL,NULL,NULL,NULL,Rofas Njagi,NULL,704573658,89254021334258495873,639021335849587,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-16 07:09:25+00,2035-07-16 23:59:59+00,1,1,nairobi,16385.58,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,regional,NULL,NULL,NULL,nairobi
865135061035133,Major Simiyu - KDS 949Y,X3,automobile,KDS 949Y,KDS 949Y,Probox,automobile,NULL,NULL,NULL,NULL,Major Simiyu,NULL,768696642,89254021394274518918,639021397451891,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2025-08-02 13:14:33+00,2035-08-02 23:59:59+00,1,1,mombasa,25089.98,2026-04-23 12:07:56.044395+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,mombasa
865135061035653,Richardson Komu - KDT 923R,X3,automobile,KDT 923R,KDT 923R,Probox,automobile,NULL,NULL,NULL,NULL,Richardson Komu,NULL,768697292,89254021394274518942,639021397451894,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-08-02 08:11:46+00,2035-08-02 23:59:59+00,1,1,mombasa,23556.65,2026-04-23 10:24:50.340401+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
865135061035778,John Kimeria - KDS 525D,X3,automobile,KDS 525D,KDS 525D,Crane,truck,NULL,NULL,NULL,NULL,John Kimeria,NULL,790176738,89254021394215205922,639021391520592,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-11 05:50:36+00,2035-07-11 23:59:59+00,1,1,nairobi,17653.96,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
865135061036164,Brian Njenga - KMFF 113Z,X3,automobile,KMFF 113Z,KMFF 113Z,Motorbike,mtc,NULL,NULL,NULL,NULL,Brian Njenga,NULL,768696705,89254021394274518850,639021397451885,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-31 10:06:46+00,2035-07-31 23:59:59+00,1,1,nairobi,22990.33,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,deliveries,NULL,NULL,NULL,nairobi
865135061037980,Emmanuel Luseno - KDS 453Y,X3,automobile,KDS 453Y,KDS 453Y,Pick-Up,automobile,NULL,NULL,NULL,NULL,Emmanuel Luseno,NULL,790176734,89254021394215205856,639021391520585,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-15 06:30:34+00,2035-07-15 23:59:59+00,1,1,nairobi,42609.03,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,general,NULL,NULL,NULL,nairobi
865135061042261,Kelvin Wambugu - KDR 592N,X3,automobile,KDR 592N,KDR 592N,Probox,automobile,NULL,NULL,NULL,NULL,Kelvin Wambugu,NULL,797680464,89254021334258159693,639021335815969,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-10 10:23:44+00,2035-07-10 23:59:59+00,1,1,nairobi,18755.66,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
865135061043079,Mike Wanaswa - KDT 724R,X3,automobile,KDT 724R,KDT 724R,Probox,automobile,NULL,NULL,NULL,NULL,Mike Wanaswa,NULL,768696664,89254021394274518959,639021397451895,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2025-08-02 12:16:11+00,2035-08-02 23:59:59+00,1,1,mombasa,27470.11,2026-04-23 11:16:35.682194+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
865135061043426,Geoffrey Karanja - KMGS 239H,X3,automobile,KMGS 239H,KMGS 239H,Motorbike,mtc,NULL,NULL,NULL,NULL,Geoffrey Karanja,NULL,768696658,89254021394274518926,639021397451892,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-08-22 13:32:25+00,2035-08-22 23:59:59+00,1,1,nairobi,21267.01,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp patrol,NULL,NULL,NULL,nairobi
865135061047435,Management_Mazda - KDU 613A,X3,automobile,KDU 613A,KDU 613A,Mazda,automobile,NULL,NULL,NULL,NULL,Management_Mazda,NULL,790175971,89254021394215205971,639021391520597,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-09 08:02:26+00,2035-07-09 23:59:59+00,1,1,nairobi,9761.38,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,management,NULL,NULL,NULL,nairobi
865135061048276,Victor Kimutai - KDS 919Y,X3,automobile,KDS 919Y,KDS 919Y,Probox,automobile,NULL,NULL,NULL,NULL,Victor Kimutai,NULL,768696755,89254021394274518900,639021397451890,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2025-08-02 07:38:01+00,2035-08-02 23:59:59+00,1,1,mombasa,23296.79,2026-04-23 10:54:41.63532+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,mombasa
865135061048300,KMGR 409U HENRY JAZZ,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,nairobi,NULL,2026-04-24 04:30:20.231102+00,2026-04-24 04:30:20.231102+00,NULL,NULL,personal,NULL,NULL,NULL,nairobi
865135061048466,Samuel Muriithy - KDR 594N,X3,automobile,KDR 594N,KDR 594N,Probox,automobile,NULL,NULL,NULL,NULL,Samuel Muriithy,NULL,797680395,89254021334258159628,639021335815962,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-07-24 09:37:31+00,2035-07-24 23:59:59+00,1,1,nairobi,27634.1,2026-04-23 11:43:39.178819+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
865135061048615,Office-KMDG 902Z,X3,automobile,KMDG 902Z,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,768697276,89254021394274518876,639021397451887,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-31 09:59:43+00,2035-07-31 23:59:59+00,1,1,nairobi,5721.21,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp patrol,NULL,NULL,NULL,nairobi
865135061048953,Timothy Gitau - KDT 916R,X3,automobile,KDT 916R,KDT 916R,Probox,automobile,NULL,NULL,NULL,NULL,Timothy Gitau,NULL,768697056,89254021394274518967,639021397451896,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2025-08-02 08:48:05+00,2035-08-02 23:59:59+00,1,1,mombasa,28536.23,2026-04-23 10:53:31.102315+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,regional,NULL,NULL,NULL,mombasa
865135061049001,Parked - KMGK 596V,X3,automobile,KMGK 596V,KMGK 596V,Motorbike,mtc,NULL,NULL,NULL,NULL,Parked,NULL,768697064,89254021394274518884,639021397451888,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-31 08:40:18+00,2035-07-31 23:59:59+00,1,1,nairobi,20612.89,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,deliveries,NULL,NULL,NULL,nairobi
865135061053714,Samuel Kihara - KMEL 225X,X3,automobile,KMEL 225X,KMEL 225X,Motorbike,mtc,NULL,NULL,NULL,NULL,Samuel Kihara,NULL,768696832,89254021394274518934,639021397451893,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-08-02 13:51:47+00,2035-08-02 23:59:59+00,1,1,nairobi,26897.18,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp patrol,NULL,NULL,NULL,nairobi
865135061053748,Rashid Hassan - KDM 840V,X3,automobile,KDM 840V,KDM 840V,Probox,automobile,NULL,NULL,NULL,NULL,Rashid Hassan,NULL,768445963,89254021334212352574,639021331235257,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-07-10 13:54:11+00,2035-07-10 23:59:59+00,1,1,mombasa,26612.42,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,mombasa
865135061054548,James Onyango - KDU 613B,X3,automobile,KDU 613B,KDU 613B,Probox,automobile,NULL,NULL,NULL,NULL,James Onyango,NULL,790175997,89254021394215205948,639021391520594,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-07-09 07:11:15+00,2035-07-09 23:59:59+00,1,1,nairobi,13446.05,2026-04-23 10:26:24.667167+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,isp,NULL,NULL,NULL,nairobi
865135061054555,Rofas Njagi - KDT 728R,X3,automobile,KDT 728R,KDT 728R,Probox,automobile,NULL,NULL,NULL,NULL,Rofas Njagi,NULL,790176726,89254021394215205823,639021391520582,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-07-16 06:44:33+00,2035-07-16 23:59:59+00,1,1,nairobi,27250.8,2026-04-23 10:25:21.085437+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,regional,NULL,NULL,NULL,nairobi
865135061559538,FRED KMGW 538W HULETI,NULL,NULL,KMGW 538W,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,null,NULL,2026-04-23 10:42:18.5831+00,2026-04-23 10:42:18.5831+00,NULL,NULL,null,NULL,NULL,NULL,null
865135061562722,John Mbugua - KDW 573B,X3,automobile,KDW 573B,KDW 573B,Probox,automobile,NULL,NULL,NULL,NULL,John Mbugua,NULL,758052508,89254021414206816832,639021410681683,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2026-01-30 06:53:57+00,2036-01-30 23:59:59+00,1,1,nairobi,4488.19,2026-04-23 10:25:38.887433+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
865135061562847,Levine Wasike - KDV 439W,X3,automobile,KDV 439W,KDV 439W,Probox,automobile,NULL,NULL,NULL,NULL,Levine Wasike,NULL,758047032,89254021414206816840,639021410681684,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2025-12-13 11:14:14+00,2035-12-13 23:59:59+00,1,1,nairobi,7880.92,2026-04-23 10:35:50.779597+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,osp,NULL,NULL,NULL,nairobi
865135061563282,X3-63282,X3,automobile,NULL,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8925610001837573427F,641101970467668,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-02-14 07:20:10+00,2036-02-14 23:59:59+00,1,1,null,4758.32,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
865135061563415,Barack Orwa - KDW 781E,X3,automobile,KDW 781E,KDW 781E,Vazel,automobile,NULL,NULL,NULL,NULL,Barack Orwa,NULL,758052541,89254021414206816931,639021410681693,Fireside_MSA,Fireside Group MSA,9d0927d235e44fe7abf254902fc68921,Default group,2026-01-13 12:37:42+00,2036-01-13 23:59:59+00,1,1,nairobi,4165.95,2026-04-23 11:22:00.676215+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,personal,NULL,NULL,NULL,nairobi
865135061563423,Joel Ntumba - UMA 826AB,X3,automobile,UMA 826AB,UMA 826AB,Motorbike,mtc,NULL,NULL,NULL,NULL,Joel Ntumba,NULL,119051036,89254021414206652690,639021410665269,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-01-28 13:55:39+00,2036-01-28 23:59:59+00,1,1,uganda,1174.05,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,mtn,NULL,NULL,NULL,uganda
865135061563597,Dominic Wambua - KDV 683Z,X3,automobile,KDV 683Z,KDV 683Z,Probox,automobile,NULL,NULL,NULL,NULL,Dominic Wambua,NULL,758052405,89254021414206816733,639021410681673,Fireside@HQ,Fireside Telematics,6ef0b0fc2d964b358b70dc2cfcbc5b7e,Default group,2026-01-30 06:55:35+00,2036-01-30 23:59:59+00,1,1,nairobi,6790.53,2026-04-23 10:25:40.125927+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,roll out,NULL,NULL,NULL,nairobi
865135061563639,Benjamin Ananda - KDV 438W,X3,automobile,KDV 438W,KDV 438W,Probox,automobile,NULL,NULL,NULL,NULL,Benjamin Ananda,NULL,758047065,89254021414206816683,639021410681668,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-12-13 16:02:37+00,2035-12-13 23:59:59+00,1,1,nairobi,14446.33,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,planning,NULL,NULL,NULL,nairobi
865135061564280,Rodin Kiberu - UMA 011EK,X3,automobile,UMA 011EK,UMA 011EK,Motorbike,mtc,NULL,NULL,NULL,NULL,Rodin Kiberu,NULL,118081642,89254021414206817244,639021410681724,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-01-28 13:13:57+00,2036-01-28 23:59:59+00,1,1,uganda,841.39,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,mtn,NULL,NULL,NULL,uganda
865135061564470,Silvanus Kipkorir - KDV 064S,X3,automobile,KDV 064S,KDV 064S,Probox,automobile,NULL,NULL,NULL,NULL,Silvanus Kipkorir,NULL,113669866,89254021414206378718,639021410637871,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-11-21 16:49:17+00,2035-11-21 23:59:59+00,1,1,nairobi,23869.16,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,airtel,NULL,NULL,NULL,nairobi
865135061568968,X3-68968,X3,automobile,NULL,NULL,NULL,automobile,NULL,NULL,NULL,NULL,NULL,NULL,NULL,89254021414206816915,639021410681691,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-03-11 06:19:14+00,2036-03-11 23:59:59+00,1,1,null,16.23,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,null,NULL,NULL,NULL,null
865135061569123,Albert Mutwiri - KDV 437W,X3,automobile,KDV 437W,KDV 437W,Probox,automobile,NULL,NULL,NULL,NULL,Albert Mutwiri,NULL,758047101,89254021414206816881,639021410681688,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-12-13 14:26:17+00,2035-12-13 23:59:59+00,1,1,nairobi,13032.6,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
865135061569131,UMA 418EK,X3,automobile,UMA 418EK,UMA 418EK,NULL,automobile,NULL,NULL,NULL,NULL,UG,NULL,256792997053,8925610001837573385F,641101970467664,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-02-26 08:15:44+00,2036-02-26 23:59:59+00,1,1,uganda,2333.45,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,mtn,NULL,NULL,NULL,uganda
865135061569479,UMA 382EK,X3,automobile,UMA 382EK,UMA 382EK,NULL,automobile,NULL,NULL,NULL,NULL,UG,NULL,256792997079,8925610001837573419F,641101970467667,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2026-02-26 08:21:10+00,2036-02-26 23:59:59+00,1,1,uganda,1954.86,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,mtn,NULL,NULL,NULL,uganda
865135061578553,X3-78553,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,unknown,null,NULL,2026-04-23 15:30:19.981271+00,2026-04-23 15:30:19.981271+00,NULL,NULL,null,NULL,NULL,NULL,null
865135061581904,Robert Kipruto - KDV 072L,X3,automobile,KDV 072L,KDV 072L,Probox,automobile,NULL,NULL,NULL,NULL,Robert Kipruto,NULL,114149576,89254021264261503993,639021266150399,fireside,Fireside Group HQ,2f1acaef6c884214b4598719180fe68d,Default group,2025-11-21 15:30:29+00,2035-11-21 23:59:59+00,1,1,nairobi,15252.84,2026-04-23 10:23:56.546784+00,2026-04-24 07:43:45.210628+00,2026-04-24 07:43:45.210628+00,NULL,fds,NULL,NULL,NULL,nairobi
1 imei device_name mc_type mc_type_use_scope vehicle_name vehicle_number vehicle_models vehicle_icon vin engine_number vehicle_brand fuel_100km driver_name driver_phone sim iccid imsi account customer_name device_group_id device_group activation_time expiration enabled_flag status city current_mileage_km created_at updated_at last_synced_at vehicle_category cost_centre assigned_route depot_geom depot_address assigned_city
2 353549090553685 Daniel Omondi - KMFF 099Z AT4 personal KMFF 099Z KMFF 099Z Motorbike mtc NULL NULL NULL NULL Robert 112794067 759336150 89254021334258404099 639021335840409 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 05:50:30+00 2040-09-23 23:59:59+00 1 1 mombasa 2354.7 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp patrol NULL NULL NULL mombasa
3 353549090561720 Wireless_Git AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 701211913 89254021374215155053 639021371515505 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-06-09 09:12:50+00 2035-06-09 23:59:59+00 1 1 mombasa 5992.43 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL regional NULL NULL NULL mombasa
4 353549090566281 KDR 592N AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 797680464 89254021334258159693 639021335815969 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-11-08 04:01:30+00 2034-11-08 23:59:59+00 1 1 nairobi 7771.9 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
5 353549090566885 Wireless GPS AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 768445963 89254021334212352574 639021331235257 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-10-15 13:16:57+00 2034-10-15 23:59:59+00 1 1 nairobi 17036.41 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL nairobi
6 353549090567685 Daniel Kipkirui - KMFF 162Z AT4 personal KMFF 162Z KMFF 162Z Motorbike mtc NULL NULL NULL NULL Daniel Kipkirui 112795498 742532058 89254021264260388966 639021266038896 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 05:09:39+00 2040-09-23 23:59:59+00 1 1 mombasa 462.33 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp patrol NULL NULL NULL mombasa
7 353549090567701 Wireless AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 790176094 89254021394215205906 639021391520590 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-11-08 04:04:44+00 2034-11-08 23:59:59+00 1 1 nairobi 16896.2 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL nairobi
8 359857081885410 Allan Owana - KDK 780K GT06E automobile KDK 780K KDK 780K Probox automobile NULL NULL NULL NULL Allan Owana NULL 703616117 89254021234222499854 639021232249985 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-19 09:32:22+00 2039-06-19 23:59:59+00 1 1 nairobi 128853.11 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
9 359857081886467 Gideon Kiprono - KCQ 215F GT06E automobile KCQ 215F OHS Probox automobile NULL NULL NULL 0 Gideon Kiprono NULL 746763076 89254021084186499865 639021088649986 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-30 09:30:00+00 2039-06-30 23:59:59+00 1 1 mombasa 141057.46 2026-04-23 10:56:37.983314+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
10 359857081886871 Kamonde KBA 467S GT06E automobile NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 746763083 89254021084186499873 639021088649987 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-30 09:09:14+00 2039-06-30 23:59:59+00 1 1 nairobi 74183.36 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL personal NULL NULL NULL nairobi
11 359857081886905 Kennedy Chege - KCQ 618K GT06E automobile KCQ 618K KCQ 618K Probox automobile NULL NULL NULL NULL Kennedy Chege NULL 746763132 89254021084186499923 639021088649992 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-30 07:08:35+00 2039-06-30 23:59:59+00 1 1 mombasa 215608.19 2026-04-23 10:35:37.678371+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
12 359857081887069 Wright Oseko - KCG 668W GT06E automobile KCG 668W KCG 668W Probox automobile NULL NULL NULL NULL Wright Oseko NULL 746763106 89254021084186499915 639021088649991 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-30 06:17:43+00 2039-06-30 23:59:59+00 1 1 nairobi 239001.19 2026-04-23 11:00:08.769463+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
13 359857081887192 Ndegwa Dancun - KCG 669W GT06E automobile KCG 669W KCG 669W Probox automobile NULL NULL NULL NULL Ndegwa Dancun NULL 746760191 89254021084186499501 639021088649950 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-15 10:26:15+00 2039-06-15 23:59:59+00 1 1 mombasa 199191.85 2026-04-23 10:34:29.074112+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
14 359857081891566 Simon Kamau - KCE 090R GT06E automobile KCE 090R KCE 090R Probox automobile NULL NULL NULL NULL Simon Kamau NULL 746760404 89254021084186499527 639021088649952 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-16 07:06:15+00 2039-06-16 23:59:59+00 1 1 nairobi 215592.36 2026-04-23 10:30:55.739184+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
15 359857081891590 Garage - KCE 699F GT06E automobile KCE 699F KCE 699F Probox automobile NULL NULL NULL NULL Garage NULL 746760215 89254021084186499519 639021088649951 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-16 11:11:24+00 2039-06-16 23:59:59+00 1 1 nairobi 207814.05 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
16 359857081891632 Samuel Kamau - KCA 542Q GT06E automobile KCA 542Q KCA 542Q Probox automobile NULL NULL NULL NULL John Ondego NULL 746760038 89254021084186499485 639021088649948 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-15 09:17:53+00 2039-06-15 23:59:59+00 1 1 nairobi 178914.47 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
17 359857081891798 Garage - KCH 167M GT06E automobile KCH 167M KCH 167M Probox automobile NULL NULL NULL NULL Garage NULL 746760102 89254021084186499493 639021088649949 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-16 10:18:57+00 2039-06-16 23:59:59+00 1 1 nairobi 168840.95 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
18 359857081892101 Cornelius Kimutai - KCU 938R GT06E automobile KCU 938R KCU 938R Van automobile NULL NULL NULL NULL Cornelius Kimutai NULL 746759919 89254021084186499451 639021088649945 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-12 08:13:48+00 2039-06-12 23:59:59+00 1 1 nairobi 149558.5 2026-04-23 10:29:21.507861+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
19 359857081892309 Nicholas Erastus - KCQ 581M GT06E automobile KCQ 581M KCQ 581M Probox automobile NULL NULL NULL NULL Nicholas Erastus NULL 700023776 89254021084178504672 639021087850467 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-09 09:39:40+00 2039-06-09 23:59:59+00 1 1 nairobi 209105.89 2026-04-23 10:40:40.169684+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
20 359857081892440 KAZ 489Z GT06E automobile NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 700023806 89254021084178504698 639021087850469 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-09 10:04:39+00 2039-06-09 23:59:59+00 1 1 nairobi 38197.2 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL personal NULL NULL NULL nairobi
21 359857081892762 Nicholas GT06E automobile NULL NULL Station Wagon bus NULL NULL Toyota NULL NULL NULL 746760503 89254021274233125361 639021273312536 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-16 08:31:46+00 2039-06-16 23:59:59+00 1 1 mombasa 51048.97 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL personal NULL NULL NULL nairobi
22 359857082037185 Amani Kazungu - KCY 084X GT06E automobile KCY 084X KCY 084X Probox automobile NULL NULL NULL NULL Amani Kazungu NULL 757338522 89254021154287000597 639021158700059 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 09:42:28+00 2040-07-13 23:59:59+00 1 1 mombasa 172298.81 2026-04-23 10:51:08.665273+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
23 359857082038977 Wilfred Kinyanjui - KCU 729C GT06E automobile KCU 729C KCU 729C Crane truck NULL NULL NULL NULL Wilfred Kinyanjui NULL 110094469 89254021164215938057 639021161593805 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-04-05 09:26:00+00 2040-04-05 23:59:59+00 1 1 nairobi 172487.09 2026-04-23 10:24:33.914628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL mombasa
24 359857082040981 Amani Sulubu - KCY 090X GT06E automobile KCY 090X KCY 090X Probox automobile NULL NULL NULL NULL Amani Sulubu NULL 793375853 89254021064168004164 639021066800416 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 07:25:16+00 2040-07-13 23:59:59+00 1 1 mombasa 166028.15 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
25 359857082042052 Gabriel Musumba - KCE 690F GT06E automobile KCE 690F KCE 690F Probox automobile NULL NULL NULL NULL Gabriel Musumba NULL 110094466 89254021164215938024 639021161593802 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2020-04-03 17:30:13+00 2040-04-03 23:59:59+00 1 1 nairobi 192693.23 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
26 359857082042854 Elias Baya - KCZ 476E GT06E automobile KCZ 476E KCZ 476E Probox automobile NULL NULL NULL NULL Elias Baya NULL 110941187 89254021164224352993 639021162435299 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-09 05:06:42+00 2040-08-09 23:59:59+00 1 1 mombasa 217595.68 2026-04-23 10:33:56.216621+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
27 359857082042953 KCU 865Q Vanguard NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown null NULL 2026-04-23 13:24:33.293453+00 2026-04-23 13:24:33.293453+00 NULL NULL null NULL NULL NULL null
28 359857082044280 Lawrence Kijogi - KCY 080X GT06E automobile KCY 080X KCY 080X Probox automobile NULL NULL NULL NULL Lawrence Kijogi NULL 708155933 89254029851005131222 639029850513122 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 11:05:02+00 2040-07-13 11:05:02+00 1 1 mombasa 169740.37 2026-04-23 14:52:58.983571+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL mombasa
29 359857082046145 Joseph Kabandi - KCY 076X GT06E automobile KCY 076X KCY 076X Probox automobile NULL NULL NULL NULL Joseph Kabandi NULL 110850007 89254021164223447158 639021162344715 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 08:31:26+00 2040-07-13 23:59:59+00 1 1 mombasa 122254.48 2026-04-23 10:47:40.895504+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
30 359857082896911 Hamisi Pande - KDD 689Y GT06E automobile KDD 689Y KDD 689Y Probox automobile NULL NULL NULL NULL Hamisi Pande NULL 112714612 89254021214211314660 639021211131466 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-09-17 11:50:53+00 2041-09-17 23:59:59+00 1 1 nairobi 163435.74 2026-04-23 10:26:09.922447+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
31 359857082897091 Peter Mbugua - KDK 728K GT06E automobile KDK 728K KDK 728K Probox automobile NULL NULL NULL NULL Peter Mbugua NULL 790262984 89254021234222500396 639021232250039 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-12-14 11:31:57+00 2042-12-14 23:59:59+00 1 1 nairobi 131109.26 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
32 359857082897257 Cassius Wakiyo - KDB 323M GT06E automobile KDB 323M KDB 323M Probox automobile NULL NULL NULL NULL Cassius Wakiyo NULL 746428882 89254021234222500818 639021232250081 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 15:07:26+00 2041-08-29 15:07:26+00 1 1 nairobi 121688.92 2026-04-23 10:28:26.388654+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
33 359857082897737 John Makori - KDB 585E GT06E automobile KDB 585E KDB 585E Probox automobile NULL NULL NULL NULL John Makori NULL 114596734 89254021214211145262 639021211114526 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 14:29:28+00 2041-08-29 14:29:28+00 1 1 nairobi 156765.03 2026-04-23 10:38:57.445964+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL planning NULL NULL NULL nairobi
34 359857082897794 Mutuku Joseph - KDC 739F GT06E automobile KDC 739F KDC 739F Probox automobile NULL NULL NULL NULL Mutuku Joseph 115019037 115019037 89254021224222632356 639021222263235 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-04-10 14:55:32+00 2041-04-10 14:55:32+00 1 1 nairobi 205169.79 2026-04-23 10:30:22.530563+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
35 359857082898008 Samuel Ng'ang'a - KDE 264M GT06E automobile KDE 264M KDE 264M Probox automobile NULL NULL NULL NULL Samuel Ng'ang'a NULL 711731539 89254021264260342245 639021266034224 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-28 09:43:11+00 2041-10-28 23:59:59+00 1 1 nairobi 126584.24 2026-04-23 11:35:59.816581+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
36 359857082898016 Job Ngare - KDM 309S GT06E automobile KDM 309S KDM 309S Probox automobile NULL NULL NULL NULL Job Ngare NULL 706895756 89254021324273007563 639021327300756 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-08-15 13:45:26+00 2033-08-15 23:59:59+00 1 1 mombasa 107726.56 2026-04-23 11:20:25.939244+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
37 359857082898073 Mutuku Antony - KDK 732K GT06E automobile KDK 732K KDK 732K Probox automobile NULL NULL NULL NULL Mutuku Antony NULL 793026954 89254021234222387539 639021232238753 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-12-20 06:33:12+00 2042-12-20 23:59:59+00 1 1 mombasa 82096.79 2026-04-23 14:52:07.094447+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
38 359857082898487 Dan Watila - KDE 638J GT06E automobile KDE 638J KDE 638J Probox automobile NULL NULL NULL NULL Dan Watila NULL 116242996 89254021334258404214 639021335840421 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-21 15:50:06+00 2041-10-21 23:59:59+00 1 1 nairobi 123872.36 2026-04-23 10:31:45.186653+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
39 359857082900168 KDD 913G_Ruth Mazda NULL NULL KDD 913G NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown nairobi NULL 2026-04-23 15:09:48.575568+00 2026-04-23 15:09:48.575568+00 NULL NULL personal NULL NULL NULL nairobi
40 359857082900341 Simon Munda - KCZ 154S GT06E automobile KCZ 154S KCZ 154S Probox automobile NULL NULL NULL NULL Simon Munda NULL 757236135 89254021154296723312 639021159672331 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 17:12:51+00 2040-09-23 23:59:59+00 1 1 mombasa 186504.1 2026-04-23 10:45:21.454595+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
41 359857082900358 Geoffrey Too - KDM 308S GT06E automobile KDM 308S KDM 308S Probox automobile NULL NULL NULL NULL Geoffrey Too NULL 796527601 89254021264260126572 639021266012657 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-21 15:25:28+00 2041-10-21 23:59:59+00 1 1 nairobi 142216.91 2026-04-23 12:35:06.661934+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
42 359857082900697 George Ochieng' - KDD 684Y GT06E automobile KDD 684Y KDD 684Y Probox automobile NULL NULL NULL NULL George Ochieng' NULL 114879518 89254021214211314678 639021211131467 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-09-17 10:53:11+00 2041-09-17 23:59:59+00 1 1 nairobi 152820.07 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
43 359857082902461 Sadique Wakayula - KDC 490Q GT06E automobile KDC 490Q KDC 490Q Crane truck NULL NULL NULL NULL Sadique Wakayula NULL 757556468 89254021154296722488 639021159672248 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-05-22 11:27:30+00 2041-05-22 11:27:30+00 1 1 mombasa 183009.52 2026-04-23 11:16:03.730519+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL mombasa
44 359857082902503 Felix Andole - KDC 207R GT06E automobile KDC 207R KDC 207R Probox automobile NULL NULL NULL NULL Felix Andole NULL 794820817 89254021224270993254 639021227099325 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-05-15 11:38:24+00 2041-05-15 11:38:24+00 1 1 mombasa 208724.46 2026-04-23 15:32:46.935568+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
45 359857082907973 Felix Muema - KCZ 223P GT06E automobile KCZ 223P KCZ 223P Probox automobile NULL NULL NULL NULL Felix Muema NULL 757843826 89254021154287138371 639021158713837 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-22 14:01:25+00 2040-08-22 23:59:59+00 1 1 mombasa 222126.36 2026-04-23 10:26:48.220151+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
46 359857082908500 Santoes Omondi - KCZ 181P GT06E automobile KCZ 181P KCZ 181P Pick-Up automobile NULL NULL NULL NULL Santoes Omondi NULL 701211974 89254021374215155087 639021371515508 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-23 08:58:55+00 2040-08-23 23:59:59+00 1 1 mombasa 221339.62 2026-04-23 10:48:09.537346+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
47 359857082910589 Patric Bett - KDA 609E GT06E automobile KDA 609E KDA 609E Probox automobile NULL NULL NULL NULL Patric Bett NULL 797622637 89254021154296722496 639021159672249 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2020-10-26 15:46:41+00 2040-10-26 23:59:59+00 1 1 nairobi 194618.69 2026-04-23 10:34:25.350862+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
48 359857082910886 Makanda Andrew - KCZ 155P GT06E automobile KCZ 155P KCZ 155P Pick-Up automobile NULL NULL NULL NULL Makanda Andrew NULL 745067338 89254021154287138397 639021158713839 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-23 11:52:35+00 2040-08-23 23:59:59+00 1 1 mombasa 231065.89 2026-04-23 11:36:31.150282+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
49 359857082911983 Brian Ngetich - KDA 717B GT06E automobile KDA 717B KDA 717B Probox automobile NULL NULL NULL NULL Brian Ngetich 795188807 795188807 89254021214211145288 639021211114528 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 07:21:43+00 2041-08-29 07:21:43+00 1 1 nairobi 145404.96 2026-04-23 10:36:11.774166+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
50 359857082912239 Dickson Jaoko - KDK 815R GT06E automobile KDK 815R KDK 815R Probox automobile NULL NULL Probox 0 Sammy NULL 706392117 89254021234296021287 639021239602128 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-06-21 07:14:51+00 2033-06-21 23:59:59+00 1 1 voi 77008.75 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
51 359857082912486 Moses Wambua - KCZ 751V GT06E automobile KCZ 751V KCZ 751V Probox automobile NULL NULL NULL NULL Moses Wambua 792756503 792756503 89254021154296723437 639021159672343 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 10:14:28+00 2040-09-23 23:59:59+00 1 1 mombasa 139762.2 2026-04-23 10:41:00.207177+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
52 359857082916826 Denis Kazungu - KDM 794R GT06E automobile KDM 794R KDM 794R Probox automobile NULL NULL NULL NULL Denis Kazungu NULL 705700971 89254021324273006854 639021327300685 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-08-21 06:38:00+00 2033-08-21 23:59:59+00 1 1 mombasa 79639.71 2026-04-23 20:18:46.496567+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
53 359857082918012 Charles Nyambane - KCB 711C GT06E automobile KCB 711C KCB 711C Probox automobile NULL NULL NULL NULL Charles Nyambane NULL 793704231 89254021154287138363 639021158713836 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2020-09-21 10:48:35+00 2040-09-21 23:59:59+00 1 1 nairobi 159597.27 2026-04-23 10:25:52.843474+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
54 359857082918038 Mbuvi Kioko - KCC 199P GT06E automobile KCC 199P KCC 199P Pick-Up automobile NULL NULL NULL NULL Mbuvi Kioko NULL 797318126 89254021154287138389 639021158713838 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-22 15:26:27+00 2040-08-22 23:59:59+00 1 1 mombasa 222106.8 2026-04-23 12:09:05.609075+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
55 359857082918186 KDD 977T Fielder NULL NULL KDD 977T NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown null NULL 2026-04-23 10:36:25.832836+00 2026-04-23 10:36:25.832836+00 NULL NULL null NULL NULL NULL null
56 359857082925330 Noel Merengeni - KCY 838X GT06E automobile KCY 838X KCY 838X Probox automobile NULL NULL NULL NULL Noel Merengeni NULL 794873610 89254021154296723429 639021159672342 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-10-26 16:36:37+00 2040-10-26 23:59:59+00 1 1 voi 194429.24 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
57 862798050288212 Nicholas Erastus - KCQ 581M JC400P automobile KCQ 581M KCQ 581M Probox automobile NULL NULL NULL NULL Nicholas Erastus NULL 746979531 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-02 09:07:41+00 2041-11-02 23:59:59+00 1 1 nairobi 40898.98 2026-04-23 13:05:18.326254+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
58 862798050288261 Patric Bett - KDA 609E JC400P automobile KDA 609E KDA 609E Probox automobile NULL NULL NULL NULL Patric Bett 112693340 790176509 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2021-10-23 11:50:11+00 2041-10-23 23:59:59+00 1 1 nairobi 18538.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
59 862798050288303 Elias Baya - KCZ 476E JC400P automobile KCZ 476E KCZ 476E Probox automobile NULL NULL NULL NULL Elias Baya NULL 115870439 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-06 08:50:28+00 2041-11-06 23:59:59+00 1 1 mombasa 116091.42 2026-04-23 17:46:09.993791+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
60 862798050288345 Santoes Omondi - KCZ 181P JC400P automobile KCZ 181P KCZ 181P Pick-Up automobile NULL NULL NULL NULL Santoes Omondi NULL 768446105 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-06 10:17:51+00 2041-11-06 23:59:59+00 1 1 mombasa 107462.79 2026-04-23 10:29:45.563231+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
61 862798050288360 Brian Ngetich - KDA 717B JC400P automobile KDA 717B KDA 717B Probox automobile NULL NULL NULL NULL Brian Ngetich NULL 717867861 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2021-11-05 08:47:08+00 2041-11-05 23:59:59+00 1 1 nairobi 17808.56 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
62 862798050521521 John Kimeria - KDS 525D JC400P automobile KDS 525D KDS 525D Crane truck NULL NULL NULL NULL John Kimeria NULL 752958416 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-11-26 07:58:13+00 2033-11-26 23:59:59+00 1 1 nairobi 19354.92 2026-04-23 10:28:34.917147+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
63 862798050521612 Denis Kazungu - KDM 794R JC400P automobile KDM 794R KDM 794R Probox automobile NULL NULL NULL NULL Denis Kazungu NULL 704113731 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-22 07:52:12+00 2042-01-22 23:59:59+00 1 1 mombasa 4350.75 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
64 862798050521752 Simon Munda - KCZ 154S JC400P automobile KCZ 154S KCZ 154S Probox automobile NULL NULL NULL NULL Simon Munda NULL 113805921 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 08:14:37+00 2042-01-16 23:59:59+00 1 1 mombasa 4698.02 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
65 862798050522065 Gideon Kiprono - KCQ 215F JC400P automobile KCQ 215F KCQ 215F Probox automobile NULL NULL NULL NULL Gideon Kiprono NULL 113343715 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-16 07:10:16+00 2042-01-16 23:59:59+00 1 1 mombasa 8111.98 2026-04-23 18:23:51.445608+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
66 862798050522107 Cassius Wakiyo - KDB 323M JC400P automobile KDB 323M KDB 323M Probox automobile NULL NULL NULL NULL Cassius Wakiyo NULL 114149576 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 08:18:15+00 2042-01-22 23:59:59+00 1 1 nairobi 23316.09 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
67 862798050522719 Mbuvi Kioko - KCZ 199P JC400P automobile KCZ 199P KCZ 199P Pick-Up automobile NULL NULL NULL NULL Mbuvi Kioko NULL 768218655 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 22:07:24+00 2042-01-16 23:59:59+00 1 1 voi 16973.89 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
68 862798050522743 Charles Nyambane - KCB 711C JC400P automobile KCB 711C KCB 711C Probox automobile NULL NULL NULL NULL Charles Nyambane NULL 768657106 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 21:53:57+00 2033-12-22 23:59:59+00 1 1 nairobi 12133.75 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
69 862798050522859 Garage - KCH 167M JC400P automobile KCH 167M KCH 167M Probox automobile NULL NULL NULL NULL Garage NULL 706740252 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 08:23:21+00 2042-01-15 23:59:59+00 1 1 nairobi 6934.86 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
70 862798050522883 Dan Watila - KDE 638J JC400P automobile KDE 638J KDE 638J Probox automobile NULL NULL NULL NULL Dan Watila NULL 112615393 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 07:17:21+00 2042-01-15 23:59:59+00 1 1 nairobi 14483.01 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
71 862798050522891 Lawrence Kijogi - KCY 080X JC400P automobile KCY 080X KCY 080X Pick-Up automobile NULL NULL NULL NULL Lawrence Kijogi NULL 113287191 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 10:51:30+00 2042-01-16 23:59:59+00 1 1 mombasa 11585.33 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL mombasa
72 862798050523014 Samuel Muriithy - KDR 594N JC400P automobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Samuel Muriithy NULL 790175423 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-21 15:54:32+00 2033-12-21 23:59:59+00 1 1 nairobi 27275.43 2026-04-23 10:26:17.747928+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
73 862798050523063 Kelvin Wambugu - KDR 594N JC400P automobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Kelvin Wambugu NULL 701211876 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 19:24:51+00 2043-12-22 19:24:51+00 1 1 nairobi 32698.94 2026-04-23 15:31:08.065856+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
74 862798050523139 Mike Wanaswa - KDT 724R JC400P automobile KDT 724R KDT 724R Probox automobile NULL NULL NULL NULL Mike Wanaswa NULL 790175045 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 22:28:09+00 2043-12-22 22:28:09+00 1 1 mombasa 29559.82 2026-04-23 11:16:37.277518+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
75 862798050523204 Amani Kazungu - KCY 084X JC400P automobile KCY 084X KCY 084X Probox automobile NULL NULL NULL NULL Amani Kazungu NULL 707892547 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 06:18:20+00 2042-01-16 23:59:59+00 1 1 mombasa 66955.7 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
76 862798050523295 Emmanuel Luseno - KDS 453 Y JC400P automobile KDS 453 Y KDS 453 Y Pick-Up automobile NULL NULL NULL NULL Emmanuel Luseno NULL 700242474 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 14:39:50+00 2033-12-22 23:59:59+00 1 1 nairobi 37098.35 2026-04-23 11:29:48.369147+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
77 862798050523337 Victor Kimutai - KDS 919Y JC400P automobile KDS 919Y KDS 919Y Probox automobile NULL NULL NULL NULL Victor Kimutai NULL 700242527 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 18:00:49+00 2043-12-22 18:00:49+00 1 1 mombasa 50756.64 2026-04-23 10:27:13.522675+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
78 862798050523386 George Ochieng' - KDD 684Y JC400P automobile KDD 684Y KDD 684Y Probox automobile NULL NULL NULL NULL George Ochieng' NULL 785586834 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 06:36:08+00 2042-01-22 23:59:59+00 1 1 nairobi 33979.83 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
79 862798050523527 Allan Owana - KDK 780K JC400P automobile KDK 780K KDK 780K Probox automobile NULL NULL NULL NULL Allan Owana NULL 792375024 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-12-03 10:43:41+00 2042-12-03 23:59:59+00 1 1 nairobi 109564.95 2026-04-23 10:25:24.360765+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
80 862798050523618 Geoffrey Too - KDM 308S JC400P automobile KDM 308S KDM 308S Probox automobile NULL NULL NULL NULL Geoffrey Too NULL 701211625 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-08-15 15:42:32+00 2033-08-15 23:59:59+00 1 1 nairobi 26496.5 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
81 862798050523626 Major Simiyu - KDS 949Y JC400P automobile KDS 949Y KDS 949Y Probox automobile NULL NULL NULL NULL Major Simiyu NULL 701211892 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 18:05:16+00 2033-12-22 23:59:59+00 1 1 mombasa 37042.97 2026-04-23 10:51:18.245194+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
82 862798050523816 Job Ngare - KDM 309S JC400P automobile KDM 309S KDM 309S Probox automobile NULL NULL NULL NULL Job Ngare NULL 707936781 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-08-15 14:05:52+00 2033-08-15 23:59:59+00 1 1 mombasa 54320.21 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
83 862798050523949 Joseph Kabandi - KCY 076X JC400P automobile KCY 076X KCY 076X Probox automobile NULL NULL NULL NULL Joseph Kabandi NULL 113288492 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 05:52:54+00 2042-01-16 23:59:59+00 1 1 mombasa 14427.5 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
84 862798050524012 Moses Wambua - KCZ 751V JC400P automobile KCZ 751V KCZ 751V Probox automobile NULL NULL NULL NULL Moses Wambua NULL 113313797 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 07:40:10+00 2042-01-16 23:59:59+00 1 1 mombasa 26551.46 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
85 862798050524087 Felix Muema - KCZ 223P JC400P automobile KCZ 223P KCZ 223P Pick-Up automobile NULL NULL NULL NULL Felix Muema NULL 113973875 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 13:02:24+00 2042-01-16 23:59:59+00 1 1 mombasa 11543.26 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
86 862798050524368 862798050524368 JC400P automobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-10-29 09:24:53+00 2042-10-29 23:59:59+00 1 1 null 169208.91 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
87 862798050524384 Hamisi Pande - KDD 689Y JC400P automobile KDD 689Y KDD 689Y Probox automobile NULL NULL NULL 0 Hamisi Pande NULL 701211744 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 05:49:19+00 2042-01-22 23:59:59+00 1 1 nairobi 13685.18 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
88 862798050524392 Ndegwa Dancun - KCG 669W JC400P automobile KCG 669W KCG 669W Probox automobile NULL NULL NULL NULL Ndegwa Dancun NULL 113799173 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 09:43:10+00 2042-01-16 23:59:59+00 1 1 mombasa 13638.25 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
89 862798050524426 Amani Sulubu - KCY 090X JC400P automobile KCY 090X KCY 090X Probox automobile NULL NULL NULL NULL Amani Sulubu NULL 113823350 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-16 08:56:25+00 2042-01-16 23:59:59+00 1 1 mombasa 14243.83 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
90 862798050524533 Leonard Nzai - KDM 306S JC400P automobile KDM 306S KDM 306S Probox automobile NULL NULL NULL NULL Leonard Nzai NULL 703487162 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-08-21 08:22:12+00 2033-08-21 23:59:59+00 1 1 mombasa 68942.41 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
91 862798050524558 Mutuku Joseph - KDC 739F JC400P automobile KDC 739F KDC 739F Probox automobile NULL NULL NULL NULL Mutuku Joseph NULL 100858817 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 10:38:25+00 2042-01-22 23:59:59+00 1 1 nairobi 23711.63 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
92 862798050524566 Makanda Andrew - KCZ 155P JC400P automobile KCZ 155P KCZ 155P Pick-Up automobile NULL NULL NULL NULL Makanda Andrew NULL 758781444 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-22 09:47:33+00 2042-01-22 23:59:59+00 1 1 mombasa 31663.3 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
93 862798050524608 Peter Mbugua - KDK 728K JC400P automobile KDK 728K KDK 728K Probox automobile NULL NULL NULL NULL Peter Mbugua NULL 706742413 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-12-03 12:11:32+00 2042-12-03 23:59:59+00 1 1 nairobi 7219.31 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
94 862798050524657 Felix Andole - KDC 207R JC400P automobile KDC 207R KDC 207R Probox automobile NULL NULL NULL NULL Felix Andole NULL 758689195 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 07:17:47+00 2042-01-22 23:59:59+00 1 1 mombasa 46233.99 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
95 862798050524681 Mutuku Antony - KDK 732K JC400P automobile KDK 732K KDK 732K Probox automobile NULL NULL NULL NULL Mutuku Antony NULL 796275746 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-12-06 13:37:49+00 2042-12-06 23:59:59+00 1 1 mombasa 14993.36 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
96 862798050524707 Garage - KCE 699F JC400P automobile KCE 699F KCE 699F Probox automobile NULL NULL NULL NULL Garage NULL 110525751 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 07:58:49+00 2042-01-15 23:59:59+00 1 1 nairobi 34715.97 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
97 862798050524897 Cornelius Kimutai - KCU 938R JC400P automobile KCU 938R KCU 938R Van automobile NULL NULL NULL NULL Cornelius Kimutai NULL 114924404 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 09:03:40+00 2042-01-22 23:59:59+00 1 1 nairobi 12668.43 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
98 862798050525068 Samuel Ng'ang'a - KDE 264M JC400P automobile KDE 264M KDE 264M Probox automobile NULL NULL NULL NULL Samuel Ng'ang'a NULL 768658564 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 13:33:42+00 2033-12-22 23:59:59+00 1 1 nairobi 12299.13 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
99 862798050525225 Sadique Wakayula - KDC 490Q JC400P automobile KDC 490Q KDC 490Q Crane truck NULL NULL NULL NULL Sadique Wakayula NULL 768652386 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 20:52:08+00 2043-12-22 20:52:08+00 1 1 mombasa 19138.05 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
100 862798050525266 Dickson Jaoko - KDK 815R JC400P automobile KDK 815R KDK 815R Probox automobile NULL NULL NULL NULL Dickson Jaoko NULL 706665867 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-06-21 07:50:00+00 2033-06-21 23:59:59+00 1 1 mombasa 63754.71 2026-04-23 13:50:24.21992+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
101 862798050525423 Makori John - KDB 585E JC400P automobile KDB 585E KDB 585E Probox automobile NULL NULL NULL NULL Makori John NULL 701211724 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 10:59:19+00 2042-01-15 23:59:59+00 1 1 mombasa 48804.83 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL planning NULL NULL NULL mombasa
102 862798050525589 Simon Kamau - KCE 090R JC400P automobile KCE 090R KCE 090R Probox automobile NULL NULL NULL NULL Simon Kamau NULL 796276387 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-19 10:10:04+00 2042-01-19 23:59:59+00 1 1 nairobi 15874.39 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
103 862798050525605 Samuel Kamau - KCA 542Q JC400P automobile KCA 542Q KCA 542Q Probox automobile NULL NULL NULL NULL John Ondego NULL 110526783 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 05:56:11+00 2042-01-15 23:59:59+00 1 1 nairobi 23976.94 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
104 862798050525613 Kennedy Chege - KCQ 618K JC400P automobile KCQ 618K KCQ 618K Probox automobile NULL NULL NULL NULL Kennedy Chege NULL 729994247 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 05:21:05+00 2042-01-16 23:59:59+00 1 1 mombasa 12804.24 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
105 862798050525670 Gabriel Musumba - KCE 690F JC400P automobile KCE 690F KCE 690F Probox automobile NULL NULL NULL NULL Gabriel Musumba NULL 701211996 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-15 06:40:01+00 2042-01-15 23:59:59+00 1 1 nairobi 20110.93 2026-04-24 05:34:23.167312+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
106 862798050525753 Noel Merengeni - KCY 838X JC400P automobile KCY 838X KCY 838X Probox automobile NULL NULL NULL NULL Noel Merengeni NULL NULL NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-15 05:24:00+00 2042-01-15 23:59:59+00 1 1 voi 14596.59 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL voi
107 862798050525837 Kennedy Ondieki - KCU 237Z JC400P automobile KCU 237Z KCU 237Z Probox automobile NULL NULL NULL NULL Kennedy Ondieki NULL 113669852 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-21 19:32:44+00 2033-12-21 23:59:59+00 1 1 nairobi NULL 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
108 862798050525951 Wright Oseko - KCG 668W JC400P automobile KCG 668W KCG 668W Probox automobile NULL NULL NULL NULL Wright Oseko NULL 741943212 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 09:36:45+00 2042-01-15 23:59:59+00 1 1 nairobi 13116 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
109 862798050526165 Wilfred Kinyanjui - KCU 729C JC400P automobile KCU 729C KCU 729C Crane truck NULL NULL NULL NULL Wilfred Kinyanjui NULL 790564929 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-11-26 10:17:19+00 2033-11-26 23:59:59+00 1 1 nairobi 24270.2 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
110 862798050526231 Rashid Hassan - KDM 840V JC400P automobile KDM 840V KDM 840V Probox automobile NULL NULL NULL NULL Rashid Hassan NULL 790175526 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 22:36:15+00 2043-12-22 22:36:15+00 1 1 mombasa 45418.38 2026-04-23 10:29:41.575467+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
111 862798050526256 Ian Dancun - KDT 923R JC400P automobile KDT 923R KDT 923R Probox automobile NULL NULL NULL NULL Ian Dancun NULL 794873610 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-12-22 19:37:24+00 2043-12-22 19:37:24+00 1 1 mombasa 11093.11 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL qehs NULL NULL NULL mombasa
112 862798052707888 Benjamin Ananda - KDV 438W JC400P automobile KDV 438W KDV 438W Probox automobile NULL NULL NULL NULL Benjamin Ananda NULL 758047312 89254021414206816980 639021410681698 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-15 07:39:23+00 2035-12-15 23:59:59+00 1 1 nairobi 8720.87 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL planning NULL NULL NULL nairobi
113 862798052707896 John Mbugua - KDW 573B JC400P automobile KDW 573B KDW 573B Probox automobile NULL NULL NULL NULL John Mbugua NULL NULL 89254021414206816725 639021410681672 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-30 14:48:17+00 2036-01-30 23:59:59+00 1 1 nairobi 515.16 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
114 862798052707946 Tom Wekesa/OSP-KCY 930Y_CAM JC400P automobile KCY 930Y NULL NULL automobile NULL NULL NULL NULL NULL NULL 758047806 89254021414206816766 639021410681676 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-20 21:02:13+00 2036-01-20 23:59:59+00 1 1 nairobi 10079.17 2026-04-23 10:25:24.363965+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
115 862798052708035 862798052708035 JC400P automobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group NULL NULL 1 1 null NULL 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
116 862798052708068 Dominic Wambua - KDV 683Z JC400P automobile KDV 683Z KDV 683Z Probox automobile NULL NULL NULL NULL Dominic Wambua NULL 758048043 89254021414206816964 639021410681696 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-24 09:20:09+00 2036-01-24 23:59:59+00 1 1 nairobi 4438.55 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
117 862798052708076 Albert Mutwiri - KDV 437W JC400P automobile KDV 437W KDV 437W Probox automobile NULL NULL NULL NULL Albert Mutwiri NULL 758047094 89254021414206816782 639021410681678 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-13 15:03:30+00 2035-12-13 23:59:59+00 1 1 nairobi 5575.64 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
118 862798052708167 Levine Wasike - KDV 439W JC400P automobile KDV 439W KDV 439W Probox automobile NULL NULL NULL NULL Levine Wasike NULL 758046738 89254021414206816741 639021410681674 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 19:49:29+00 2035-12-13 23:59:59+00 1 1 nairobi 4601.08 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
119 862798052708282 Godffrey Nandwa - KCN 496A JC400P automobile KCN 496A KCN 496A Probox automobile NULL NULL NULL NULL Godffrey Nandwa NULL 758047934 89254021414206816865 639021410681686 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-25 18:55:54+00 2036-01-25 23:59:59+00 1 1 nairobi 7040.6 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
120 862798052713654 Garage/ISP_KCL 502T_CAM JC400P automobile KCL 502T NULL NULL automobile NULL NULL NULL NULL NULL NULL 780215879 89254035061001753803 639035060175380 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-09-02 10:09:57+00 2035-09-02 23:59:59+00 1 1 nairobi 5199.72 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
121 862798052713696 862798052713696 JC400P automobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL 89254021394215205906 639021391520590 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-09-02 10:20:58+00 2035-09-02 23:59:59+00 1 1 null 6214.49 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
122 862798052713761 Management_Mazda - KDU 613A JC400P automobile KDU 613A KDU 613A Mazda automobile NULL NULL NULL NULL Management_Mazda NULL 790176786 89254021394215205955 639021391520595 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-09 15:49:26+00 2035-07-09 23:59:59+00 1 1 nairobi 9262.78 2026-04-23 16:40:48.879666+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL management NULL NULL NULL nairobi
123 862798052713779 Benard Kimutai - KDN 759G JC400P automobile KDN 759G KDN 759G Probox automobile NULL NULL NULL NULL Benard Kimutai NULL 752143258 89254035061001753860 639035060175386 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-23 11:15:59+00 2035-08-23 23:59:59+00 1 1 nairobi 5344.24 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
124 862798052713811 James Onyango - KDU 613B JC400P automobile KDU 613B KDU 613B Probox automobile NULL NULL NULL NULL James Onyango NULL 790176542 89254021394215205880 639021391520588 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-09 19:24:14+00 2035-07-09 23:59:59+00 1 1 nairobi 9657.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
125 862798052713837 Kennedy Ondieki - KCU 237Z JC400P automobile KCU 237Z KCU 237Z Probox automobile NULL NULL NULL NULL Kennedy Ondieki NULL 113669852 89254021414206327855 639021410632785 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-10-08 14:55:23+00 2035-10-08 23:59:59+00 1 1 nairobi 9346.02 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
126 862798052713985 Timothy Gitau - KDT 916R JC400P automobile KDT 916R KDT 916R Probox automobile NULL NULL NULL NULL Timothy Gitau NULL 768696668 89254021394274518892 639021397451889 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-08-02 18:21:23+00 2035-08-02 23:59:59+00 1 1 mombasa 19998.22 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL regional NULL NULL NULL mombasa
127 862798052714066 862798052714066 JC400P automobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL 89254021414206378684 639021410637868 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-11-21 17:44:44+00 2035-11-21 23:59:59+00 1 1 null 10755.28 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
128 862798052715220 Rofas Njagi - KDT 728R JC400P automobile KDT 728R KDT 728R Probox automobile NULL NULL NULL NULL Rofas Njagi NULL 704573658 89254021334258495873 639021335849587 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-16 07:09:25+00 2035-07-16 23:59:59+00 1 1 nairobi 16385.58 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL regional NULL NULL NULL nairobi
129 865135061035133 Major Simiyu - KDS 949Y X3 automobile KDS 949Y KDS 949Y Probox automobile NULL NULL NULL NULL Major Simiyu NULL 768696642 89254021394274518918 639021397451891 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 13:14:33+00 2035-08-02 23:59:59+00 1 1 mombasa 25089.98 2026-04-23 12:07:56.044395+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL mombasa
130 865135061035653 Richardson Komu - KDT 923R X3 automobile KDT 923R KDT 923R Probox automobile NULL NULL NULL NULL Richardson Komu NULL 768697292 89254021394274518942 639021397451894 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-08-02 08:11:46+00 2035-08-02 23:59:59+00 1 1 mombasa 23556.65 2026-04-23 10:24:50.340401+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
131 865135061035778 John Kimeria - KDS 525D X3 automobile KDS 525D KDS 525D Crane truck NULL NULL NULL NULL John Kimeria NULL 790176738 89254021394215205922 639021391520592 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-11 05:50:36+00 2035-07-11 23:59:59+00 1 1 nairobi 17653.96 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
132 865135061036164 Brian Njenga - KMFF 113Z X3 automobile KMFF 113Z KMFF 113Z Motorbike mtc NULL NULL NULL NULL Brian Njenga NULL 768696705 89254021394274518850 639021397451885 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 10:06:46+00 2035-07-31 23:59:59+00 1 1 nairobi 22990.33 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL deliveries NULL NULL NULL nairobi
133 865135061037980 Emmanuel Luseno - KDS 453Y X3 automobile KDS 453Y KDS 453Y Pick-Up automobile NULL NULL NULL NULL Emmanuel Luseno NULL 790176734 89254021394215205856 639021391520585 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-15 06:30:34+00 2035-07-15 23:59:59+00 1 1 nairobi 42609.03 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL general NULL NULL NULL nairobi
134 865135061042261 Kelvin Wambugu - KDR 592N X3 automobile KDR 592N KDR 592N Probox automobile NULL NULL NULL NULL Kelvin Wambugu NULL 797680464 89254021334258159693 639021335815969 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-10 10:23:44+00 2035-07-10 23:59:59+00 1 1 nairobi 18755.66 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
135 865135061043079 Mike Wanaswa - KDT 724R X3 automobile KDT 724R KDT 724R Probox automobile NULL NULL NULL NULL Mike Wanaswa NULL 768696664 89254021394274518959 639021397451895 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 12:16:11+00 2035-08-02 23:59:59+00 1 1 mombasa 27470.11 2026-04-23 11:16:35.682194+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
136 865135061043426 Geoffrey Karanja - KMGS 239H X3 automobile KMGS 239H KMGS 239H Motorbike mtc NULL NULL NULL NULL Geoffrey Karanja NULL 768696658 89254021394274518926 639021397451892 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-22 13:32:25+00 2035-08-22 23:59:59+00 1 1 nairobi 21267.01 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp patrol NULL NULL NULL nairobi
137 865135061047435 Management_Mazda - KDU 613A X3 automobile KDU 613A KDU 613A Mazda automobile NULL NULL NULL NULL Management_Mazda NULL 790175971 89254021394215205971 639021391520597 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-09 08:02:26+00 2035-07-09 23:59:59+00 1 1 nairobi 9761.38 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL management NULL NULL NULL nairobi
138 865135061048276 Victor Kimutai - KDS 919Y X3 automobile KDS 919Y KDS 919Y Probox automobile NULL NULL NULL NULL Victor Kimutai NULL 768696755 89254021394274518900 639021397451890 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 07:38:01+00 2035-08-02 23:59:59+00 1 1 mombasa 23296.79 2026-04-23 10:54:41.63532+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL mombasa
139 865135061048300 KMGR 409U HENRY JAZZ NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown nairobi NULL 2026-04-24 04:30:20.231102+00 2026-04-24 04:30:20.231102+00 NULL NULL personal NULL NULL NULL nairobi
140 865135061048466 Samuel Muriithy - KDR 594N X3 automobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Samuel Muriithy NULL 797680395 89254021334258159628 639021335815962 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-24 09:37:31+00 2035-07-24 23:59:59+00 1 1 nairobi 27634.1 2026-04-23 11:43:39.178819+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
141 865135061048615 Office-KMDG 902Z X3 automobile KMDG 902Z NULL NULL automobile NULL NULL NULL NULL NULL NULL 768697276 89254021394274518876 639021397451887 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 09:59:43+00 2035-07-31 23:59:59+00 1 1 nairobi 5721.21 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp patrol NULL NULL NULL nairobi
142 865135061048953 Timothy Gitau - KDT 916R X3 automobile KDT 916R KDT 916R Probox automobile NULL NULL NULL NULL Timothy Gitau NULL 768697056 89254021394274518967 639021397451896 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 08:48:05+00 2035-08-02 23:59:59+00 1 1 mombasa 28536.23 2026-04-23 10:53:31.102315+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL regional NULL NULL NULL mombasa
143 865135061049001 Parked - KMGK 596V X3 automobile KMGK 596V KMGK 596V Motorbike mtc NULL NULL NULL NULL Parked NULL 768697064 89254021394274518884 639021397451888 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 08:40:18+00 2035-07-31 23:59:59+00 1 1 nairobi 20612.89 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL deliveries NULL NULL NULL nairobi
144 865135061053714 Samuel Kihara - KMEL 225X X3 automobile KMEL 225X KMEL 225X Motorbike mtc NULL NULL NULL NULL Samuel Kihara NULL 768696832 89254021394274518934 639021397451893 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-02 13:51:47+00 2035-08-02 23:59:59+00 1 1 nairobi 26897.18 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp patrol NULL NULL NULL nairobi
145 865135061053748 Rashid Hassan - KDM 840V X3 automobile KDM 840V KDM 840V Probox automobile NULL NULL NULL NULL Rashid Hassan NULL 768445963 89254021334212352574 639021331235257 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-10 13:54:11+00 2035-07-10 23:59:59+00 1 1 mombasa 26612.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL mombasa
146 865135061054548 James Onyango - KDU 613B X3 automobile KDU 613B KDU 613B Probox automobile NULL NULL NULL NULL James Onyango NULL 790175997 89254021394215205948 639021391520594 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-09 07:11:15+00 2035-07-09 23:59:59+00 1 1 nairobi 13446.05 2026-04-23 10:26:24.667167+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL isp NULL NULL NULL nairobi
147 865135061054555 Rofas Njagi - KDT 728R X3 automobile KDT 728R KDT 728R Probox automobile NULL NULL NULL NULL Rofas Njagi NULL 790176726 89254021394215205823 639021391520582 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-16 06:44:33+00 2035-07-16 23:59:59+00 1 1 nairobi 27250.8 2026-04-23 10:25:21.085437+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL regional NULL NULL NULL nairobi
148 865135061559538 FRED KMGW 538W HULETI NULL NULL KMGW 538W NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown null NULL 2026-04-23 10:42:18.5831+00 2026-04-23 10:42:18.5831+00 NULL NULL null NULL NULL NULL null
149 865135061562722 John Mbugua - KDW 573B X3 automobile KDW 573B KDW 573B Probox automobile NULL NULL NULL NULL John Mbugua NULL 758052508 89254021414206816832 639021410681683 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-30 06:53:57+00 2036-01-30 23:59:59+00 1 1 nairobi 4488.19 2026-04-23 10:25:38.887433+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
150 865135061562847 Levine Wasike - KDV 439W X3 automobile KDV 439W KDV 439W Probox automobile NULL NULL NULL NULL Levine Wasike NULL 758047032 89254021414206816840 639021410681684 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-13 11:14:14+00 2035-12-13 23:59:59+00 1 1 nairobi 7880.92 2026-04-23 10:35:50.779597+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL osp NULL NULL NULL nairobi
151 865135061563282 X3-63282 X3 automobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL 8925610001837573427F 641101970467668 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-14 07:20:10+00 2036-02-14 23:59:59+00 1 1 null 4758.32 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
152 865135061563415 Barack Orwa - KDW 781E X3 automobile KDW 781E KDW 781E Vazel automobile NULL NULL NULL NULL Barack Orwa NULL 758052541 89254021414206816931 639021410681693 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2026-01-13 12:37:42+00 2036-01-13 23:59:59+00 1 1 nairobi 4165.95 2026-04-23 11:22:00.676215+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL personal NULL NULL NULL nairobi
153 865135061563423 Joel Ntumba - UMA 826AB X3 automobile UMA 826AB UMA 826AB Motorbike mtc NULL NULL NULL NULL Joel Ntumba NULL 119051036 89254021414206652690 639021410665269 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-28 13:55:39+00 2036-01-28 23:59:59+00 1 1 uganda 1174.05 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL mtn NULL NULL NULL uganda
154 865135061563597 Dominic Wambua - KDV 683Z X3 automobile KDV 683Z KDV 683Z Probox automobile NULL NULL NULL NULL Dominic Wambua NULL 758052405 89254021414206816733 639021410681673 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-30 06:55:35+00 2036-01-30 23:59:59+00 1 1 nairobi 6790.53 2026-04-23 10:25:40.125927+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL roll out NULL NULL NULL nairobi
155 865135061563639 Benjamin Ananda - KDV 438W X3 automobile KDV 438W KDV 438W Probox automobile NULL NULL NULL NULL Benjamin Ananda NULL 758047065 89254021414206816683 639021410681668 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 16:02:37+00 2035-12-13 23:59:59+00 1 1 nairobi 14446.33 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL planning NULL NULL NULL nairobi
156 865135061564280 Rodin Kiberu - UMA 011EK X3 automobile UMA 011EK UMA 011EK Motorbike mtc NULL NULL NULL NULL Rodin Kiberu NULL 118081642 89254021414206817244 639021410681724 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-28 13:13:57+00 2036-01-28 23:59:59+00 1 1 uganda 841.39 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL mtn NULL NULL NULL uganda
157 865135061564470 Silvanus Kipkorir - KDV 064S X3 automobile KDV 064S KDV 064S Probox automobile NULL NULL NULL NULL Silvanus Kipkorir NULL 113669866 89254021414206378718 639021410637871 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-11-21 16:49:17+00 2035-11-21 23:59:59+00 1 1 nairobi 23869.16 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL airtel NULL NULL NULL nairobi
158 865135061568968 X3-68968 X3 automobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL 89254021414206816915 639021410681691 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-03-11 06:19:14+00 2036-03-11 23:59:59+00 1 1 null 16.23 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL null NULL NULL NULL null
159 865135061569123 Albert Mutwiri - KDV 437W X3 automobile KDV 437W KDV 437W Probox automobile NULL NULL NULL NULL Albert Mutwiri NULL 758047101 89254021414206816881 639021410681688 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 14:26:17+00 2035-12-13 23:59:59+00 1 1 nairobi 13032.6 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi
160 865135061569131 UMA 418EK X3 automobile UMA 418EK UMA 418EK NULL automobile NULL NULL NULL NULL UG NULL 256792997053 8925610001837573385F 641101970467664 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-26 08:15:44+00 2036-02-26 23:59:59+00 1 1 uganda 2333.45 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL mtn NULL NULL NULL uganda
161 865135061569479 UMA 382EK X3 automobile UMA 382EK UMA 382EK NULL automobile NULL NULL NULL NULL UG NULL 256792997079 8925610001837573419F 641101970467667 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-26 08:21:10+00 2036-02-26 23:59:59+00 1 1 uganda 1954.86 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL mtn NULL NULL NULL uganda
162 865135061578553 X3-78553 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown null NULL 2026-04-23 15:30:19.981271+00 2026-04-23 15:30:19.981271+00 NULL NULL null NULL NULL NULL null
163 865135061581904 Robert Kipruto - KDV 072L X3 automobile KDV 072L KDV 072L Probox automobile NULL NULL NULL NULL Robert Kipruto NULL 114149576 89254021264261503993 639021266150399 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-11-21 15:30:29+00 2035-11-21 23:59:59+00 1 1 nairobi 15252.84 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL fds NULL NULL NULL nairobi

View file

@ -1,145 +0,0 @@
IMEI,Device Name,Vehicle Name,Vehicle Icon,License Plate No.,Vehicle Model,Vehicle Brand,Driver Name,Telephone,SIM,Fuel/100km,VIN,Engine Number,Remarks,Group,Department,Account,Customer Name,Model,Activated Date,Sales Time,MAC,Subscription Expiration,User Expiration Date,Battery replacement date,ICCID,IMSI,ID Number,Installation Time
865135061569479,UMA 382EK,UMA 382EK,automobile,UMA 382EK,,,UG,,+256792997079,,,,Dept: MTN,Default Group,MTN,fireside,Fireside Group HQ,X3,2026-02-26,2025-09-08,,2036-02-27,2036-02-27,,8925610001837573419F,641101970467667,,
865135061569131,UMA 418EK,UMA 418EK,automobile,UMA 418EK,,,UG,,+256792997053,,,,Dept: MTN,Default Group,MTN,fireside,Fireside Group HQ,X3,2026-02-26,2025-09-08,,2036-02-27,2036-02-27,,8925610001837573385F,641101970467664,,
862798052707896,John Mbugua - KDW 573B,KDW 573B,automobile,KDW 573B,Probox,,John Mbugua,,,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2026-01-30,2025-06-11,,2036-01-31,2036-01-31,,89254021414206816725,639021410681672,,
865135061563423,Joel Ntumba - UMA 826AB,UMA 826AB,mtc,UMA 826AB,Motorbike,,Joel Ntumba,,0119051036,,,,Dept: MTN,Default Group,MTN,fireside,Fireside Group HQ,X3,2026-01-28,2025-09-08,,2036-01-29,2036-01-29,,89254021414206652690,639021410665269,,
865135061564280,Rodin Kiberu - UMA 011EK,UMA 011EK,mtc,UMA 011EK,Motorbike,,Rodin Kiberu,,0118081642,,,,Dept: MTN,Default Group,MTN,fireside,Fireside Group HQ,X3,2026-01-28,2025-09-08,,2036-01-29,2036-01-29,,89254021414206817244,639021410681724,,
862798052708068,Dominic Wambua - KDV 683Z,KDV 683Z,automobile,KDV 683Z,Probox,,Dominic Wambua,,0758048043,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Group HQ,JC400P,2026-01-24,2025-06-11,,2036-01-25,2036-01-25,,89254021414206816964,639021410681696,,
862798052708167,Levine Wasike - KDV 439W,KDV 439W,automobile,KDV 439W,Probox,,Levine Wasike,,0758046738,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,JC400P,2025-12-13,2025-06-11,,2035-12-14,2035-12-14,,89254021414206816741,639021410681674,,
865135061563639,Benjamin Ananda - KDV 438W,KDV 438W,automobile,KDV 438W,Probox,,Benjamin Ananda,,0758047065,,,,Dept: PLANNING,Default Group,PLANNING,fireside,Fireside Group HQ,X3,2025-12-13,2025-09-08,,2035-12-14,2035-12-14,,89254021414206816683,639021410681668,,
865135061569123,Albert Mutwiri - KDV 437W,KDV 437W,automobile,KDV 437W,Probox,,Albert Mutwiri,,0758047101,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,X3,2025-12-13,2025-09-08,,2035-12-14,2035-12-14,,89254021414206816881,639021410681688,,
865135061564470,Silvanus Kipkorir - KDV 064S,KDV 064S,automobile,KDV 064S,Probox,,Silvanus Kipkorir,,0113669866,,,,Dept: AIRTEL,Default Group,AIRTEL,fireside,Fireside Group HQ,X3,2025-11-21,2025-09-08,,2035-11-22,2035-11-22,,89254021414206378718,639021410637871,,
865135061581904,Robert Kipruto - KDV 072L,KDV 072L,automobile,KDV 072L,Probox,,Robert Kipruto,,0114149576,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,X3,2025-11-21,2025-09-08,,2035-11-22,2035-11-22,,89254021264261503993,639021266150399,,
862798052713779,Benard Kimutai - KDN 759G,KDN 759G,automobile,KDN 759G,Probox,,Benard Kimutai,,0752143258,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2025-08-23,2025-06-11,,2035-08-24,2035-08-24,,89254035061001753860,639035060175386,,
865135061043426,Geoffrey Karanja - KMGS 239H,KMGS 239H,mtc,KMGS 239H,Motorbike,,Geoffrey Karanja,,0768696658,,,,Dept: OSP-PATROL,Default Group,OSP-PATROL,fireside,Fireside Group HQ,X3,2025-08-22,2025-06-11,,2035-08-23,2035-08-23,,89254021394274518926,639021397451892,,
865135061053714,Samuel Kihara - KMEL 225X,KMEL 225X,mtc,KMEL 225X,Motorbike,,Samuel Kihara,,0768696832,,,,Dept: OSP-PATROL,Default Group,OSP-PATROL,fireside,Fireside Group HQ,X3,2025-08-02,2025-06-11,,2035-08-03,2035-08-03,,89254021394274518934,639021397451893,,
865135061036164,Brian Njenga - KMFF 113Z,KMFF 113Z,mtc,KMFF 113Z,Motorbike,,Brian Njenga,,0768696705,,,,Dept: OSP-PATROL,Default Group,OSP-PATROL,fireside,Fireside Group HQ,X3,2025-07-31,2025-06-11,,2035-08-01,2035-08-01,,89254021394274518850,639021397451885,,
865135061049001,Parked - KMGK 596V,KMGK 596V,mtc,KMGK 596V,Motorbike,,Parked,,0768697064,,,,Dept: DELIVERIES,Default Group,DELIVERIES,fireside,Fireside Group HQ,X3,2025-07-31,2025-06-11,,2035-08-01,2035-08-01,,89254021394274518884,639021397451888,,
862798052715220,Rofas Njagi - KDT 728R,KDT 728R,automobile,KDT 728R,Probox,,Rofas Njagi,,0704573658,,,,Dept: REGIONAL,Default Group,REGIONAL,fireside,Fireside Group HQ,JC400P,2025-07-16,2025-06-11,,2035-07-17,2035-07-17,,89254021334258495873,639021335849587,,
865135061037980,Emmanuel Luseno - KDS 453Y,KDS 453Y,automobile,KDS 453Y,Pick-Up,,Emmanuel Luseno,,0790176734,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Group HQ,X3,2025-07-15,2025-06-11,,,2035-07-15,,89254021394215205856,639021391520585,,
865135061035778,John Kimeria - KDS 525D,KDS 525D,truck,KDS 525D,Crane,,John Kimeria,,0790176738,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Group HQ,X3,2025-07-11,2025-06-11,,2035-07-12,2035-07-12,,89254021394215205922,639021391520592,,
865135061053748,Rashid Hassan - KDM 840V,KDM 840V,automobile,KDM 840V,Probox,,Rashid Hassan,,0768445963,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,X3,2025-07-10,2025-06-11,,2035-07-11,2035-07-11,,89254021334212352574,639021331235257,,
865135061042261,Kelvin Wambugu - KDR 592N,KDR 592N,automobile,KDR 592N,Probox,,Kelvin Wambugu,,0797680464,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,X3,2025-07-10,2025-06-11,,2035-07-11,2035-07-11,,89254021334258159693,639021335815969,,
862798052713811,James Onyango - KDU 613B,KDU 613B,automobile,KDU 613B,Probox,,James Onyango,,0790176542,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2025-07-09,2025-06-11,,2035-07-10,2035-07-10,,89254021394215205880,639021391520588,,
865135061047435,Management_Mazda - KDU 613A,KDU 613A,automobile,KDU 613A,Mazda,,Management_Mazda,,0790175971,,,,Dept: MGT,Default Group,MGT,fireside,Fireside Group HQ,X3,2025-07-09,2025-06-11,,2035-07-10,2035-07-10,,89254021394215205971,639021391520597,,
862798050522743,Charles Nyambane - KCB 711C,KCB 711C,automobile,KCB 711C,Probox,,Charles Nyambane,,0768657106,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2023-12-22,2024-11-08,,2033-12-23,2033-12-23,,,,,
862798050525225,Sadique Wakayula - KDC 490Q,KDC 490Q,truck,KDC 490Q,Crane,,Sadique Wakayula,,0768652386,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Group HQ,JC400P,2023-12-22,2024-11-08,,2043-12-22,2043-12-22,,,,,
862798050525068,Samuel Ng'ang'a - KDE 264M,KDE 264M,automobile,KDE 264M,Probox,,Samuel Ng'ang'a,,0768658564,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2023-12-22,2024-11-08,,2033-12-23,2033-12-23,,,,,
862798050525837,Kennedy Ondieki - KCU 237Z,KCU 237Z,automobile,KCU 237Z,Probox,,Kennedy Ondieki,,0113669852,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2023-12-21,,,2033-12-22,2033-12-22,,,,,
862798050523618,Geoffrey Too - KDM 308S,KDM 308S,automobile,KDM 308S,Probox,,Geoffrey Too,,0701211625,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2023-08-15,2023-08-22,,2033-08-16,2033-08-16,,,,,
862798050523816,Job Ngare - KDM 309S,KDM 309S,automobile,KDM 309S,Probox,,Job Ngare,,0707936781,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2023-08-15,2023-08-22,,2033-08-16,2033-08-16,,,,,
359857082912239,Dickson Jaoko - KDK 815R,KDK 815R,automobile,KDK 815R,Probox,,Dickson Jaoko,,0706392117,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,GT06E,2023-06-21,2023-07-27,,2033-06-22,2033-06-22,,89254021234296021287,639021239602128,,
359857082897091,Peter Mbugua - KDK 728K,KDK 728K,automobile,KDK 728K,Probox,,Peter Mbugua,,0790262984,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,GT06E,2022-12-14,2022-12-16,,2042-12-15,2042-12-15,,89254021234222500396,639021232250039,,
862798050524608,Peter Mbugua - KDK 728K,KDK 728K,automobile,KDK 728K,Probox,,Peter Mbugua,,0706742413,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-12-03,2022-12-15,,2042-12-04,2042-12-04,,,,,
862798050524368,862798050524368,,automobile,,,,,,,,,,,Default Group,,fireside,Fireside Group HQ,JC400P,2022-10-29,2022-12-17,,2042-10-30,2042-10-30,,,,,
862798050524558,Mutuku Joseph - KDC 739F,KDC 739F,automobile,KDC 739F,Probox,,Mutuku Joseph,,0100858817,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-25,,2042-01-23,2042-01-23,,,,,
862798050524897,Cornelius Kimutai - KCU 938R,KCU 938R,automobile,KCU 938R,Van,,Cornelius Kimutai,,0114924404,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-25,,2042-01-23,2042-01-23,,,,,
862798050522107,Cassius Wakiyo - KDB 323M,KDB 323M,automobile,KDB 323M,Probox,,Cassius Wakiyo,,0114149576,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-25,,2042-01-23,2042-01-23,,,,,
862798050524657,Felix Andole - KDC 207R,KDC 207R,automobile,KDC 207R,Probox,,Felix Andole,,0758689195,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-25,,2042-01-23,2042-01-23,,,,,
862798050523386,George Ochieng' - KDD 684Y,KDD 684Y,automobile,KDD 684Y,Probox,,George Ochieng',,0785586834,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-27,,2042-01-23,2042-01-23,,,,,
862798050524384,Hamisi Pande - KDD 689Y,KDD 689Y,automobile,KDD 689Y,Probox,,Hamisi Pande,,0701211744,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-01-22,2022-01-27,,2042-01-23,2042-01-23,,,,,
862798050525589,Simon Kamau - KCE 090R,KCE 090R,automobile,KCE 090R,Probox,,Simon Kamau,,0796276387,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-01-19,2022-01-17,,2042-01-20,2042-01-20,,,,,
862798050525423,Makori John - KDB 585E,KDB 585E,automobile,KDB 585E,Probox,,Makori John,,0701211724,,,,Dept: PLANNING,Default Group,PLANNING,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050525951,Wright Oseko - KCG 668W,KCG 668W,automobile,KCG 668W,Probox,,Wright Oseko,,0741943212,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050522859,Garage - KCH 167M,KCH 167M,automobile,KCH 167M,Probox,,Garage,,0706740252,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050524707,Garage - KCE 699F,KCE 699F,automobile,KCE 699F,Probox,,Garage,,0110525751,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050522883,Dan Watila - KDE 638J,KDE 638J,automobile,KDE 638J,Probox,,Dan Watila,,0112615393,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050525605,John Ondego - KCA 542Q,KCA 542Q,automobile,KCA 542Q,Probox,,John Ondego,,0110526783,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2022-01-15,2022-01-17,,2042-01-16,2042-01-16,,,,,
862798050288360,Brian Ngetich - KDA 717B,KDA 717B,automobile,KDA 717B,Probox,,Brian Ngetich,,0717867861,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,JC400P,2021-11-05,2021-11-08,,2041-11-06,2041-11-06,,,,,
862798050288261,Patric Bett - KDA 609E,KDA 609E,automobile,KDA 609E,Probox,,Patric Bett,0112693340,0790176509,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,JC400P,2021-10-23,2021-10-25,,2041-10-24,2041-10-24,,,,,
359857082042052,Gabriel Musumba - KCE 690F,KCE 690F,automobile,KCE 690F,Probox,,Gabriel Musumba,,0110094466,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,GT06E,2020-04-03,2020-04-16,,2040-04-04,2040-04-04,,89254021164215938024,639021161593802,,
359857081885410,Allan Owana - KDK 780K,KDK 780K,automobile,KDK 780K,Probox,,Allan Owana,,0703616117,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,GT06E,2019-06-19,2019-07-01,,2039-06-20,2039-06-20,,89254021234222499854,639021232249985,,
359857081891798,Garage - KCH 167M,KCH 167M,automobile,KCH 167M,Probox,,Garage,,0746760102,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group HQ,GT06E,2019-06-16,2019-07-01,,2039-06-17,2039-06-17,,89254021084186499493,639021088649949,,
359857081891632,John Ondego - KCA 542Q,KCA 542Q,automobile,KCA 542Q,Probox,,John Ondego,,0746760038,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group HQ,GT06E,2019-06-15,2019-07-01,,2039-06-16,2039-06-16,,89254021084186499485,639021088649948,,
862798052708035,862798052708035,,automobile,,Probox,,,,,,,,,Default Group,,fireside,Fireside Group HQ,JC400P,Inactive,2025-06-11,,120Month,——,,,,,
865135061563597,Dominic Wambua - KDV 683Z,KDV 683Z,automobile,KDV 683Z,Probox,,Dominic Wambua,,0758052405,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Telematics ,X3,2026-01-30,2026-02-24,,2036-01-31,2036-01-31,,89254021414206816733,639021410681673,,
865135061562722,John Mbugua - KDW 573B,KDW 573B,automobile,KDW 573B,Probox,,John Mbugua,,0758052508,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,X3,2026-01-30,2026-02-24,,2036-01-31,2036-01-31,,89254021414206816832,639021410681683,,
862798052708282,Godffrey Nandwa - KCN 496A,KCN 496A,automobile,KCN 496A,Probox,,Godffrey Nandwa,,0758047934,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2026-01-25,2026-02-20,,2036-01-26,2036-01-26,,89254021414206816865,639021410681686,,
862798052707888,Benjamin Ananda - KDV 438W,KDV 438W,automobile,KDV 438W,Probox,,Benjamin Ananda,,0758047312,,,,Dept: PLANNING,Default Group,PLANNING,fireside,Fireside Telematics ,JC400P,2025-12-15,2026-02-20,,2035-12-16,2035-12-16,,89254021414206816980,639021410681698,,
862798052708076,Albert Mutwiri - KDV 437W,KDV 437W,automobile,KDV 437W,Probox,,Albert Mutwiri,,0758047094,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,JC400P,2025-12-13,2026-02-20,,2035-12-14,2035-12-14,,89254021414206816782,639021410681678,,
865135061562847,Levine Wasike - KDV 439W,KDV 439W,automobile,KDV 439W,Probox,,Levine Wasike,,0758047032,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,X3,2025-12-13,2026-02-24,,2035-12-14,2035-12-14,,89254021414206816840,639021410681684,,
862798052714066,862798052714066,,automobile,,Probox,,,,,,,,,Default Group,,fireside,Fireside Telematics ,JC400P,2025-11-21,2025-06-11,,2035-11-22,2035-11-22,,89254021414206378684,639021410637868,,
862798052713837,Kennedy Ondieki - KCU 237Z,KCU 237Z,automobile,KCU 237Z,Probox,,Kennedy Ondieki,,0113669852,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2025-10-08,2026-02-20,,2035-10-09,2035-10-09,,89254021414206327855,639021410632785,,
862798052713696,862798052713696,,automobile,,Probox,,,,,,,,,Default Group,,fireside,Fireside Telematics ,JC400P,2025-09-02,2025-06-11,,2035-09-03,2035-09-03,,89254021394215205906,639021391520590,,
862798052713985,Timothy Gitau - KDT 916R,KDT 916R,automobile,KDT 916R,Probox,,Timothy Gitau,,0768696668,,,,Dept: REGIONAL,Default Group,REGIONAL,fireside,Fireside Telematics ,JC400P,2025-08-02,2026-02-20,,2035-08-03,2035-08-03,,89254021394274518892,639021397451889,,
865135061035653,Richardson Komu - KDT 923R,KDT 923R,automobile,KDT 923R,Probox,,Richardson Komu,,0768697292,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,X3,2025-08-02,2026-02-24,,2035-08-03,2035-08-03,,89254021394274518942,639021397451894,,
865135061048466,Samuel Muriithy - KDR 594N,KDR 594N,automobile,KDR 594N,Probox,,Samuel Muriithy,,0797680395,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Telematics ,X3,2025-07-24,2026-02-24,,2035-07-25,2035-07-25,,89254021334258159628,639021335815962,,
865135061054555,Rofas Njagi - KDT 728R,KDT 728R,automobile,KDT 728R,Probox,,Rofas Njagi,,0790176726,,,,Dept: REGIONAL,Default Group,REGIONAL,fireside,Fireside Telematics ,X3,2025-07-16,2026-02-24,,2035-07-17,2035-07-17,,89254021394215205823,639021391520582,,
862798052713761,Management_Mazda - KDU 613A,KDU 613A,automobile,KDU 613A,Mazda,,Management_Mazda,,0790176786,,,,Dept: MGT,Default Group,MGT,fireside,Fireside Telematics ,JC400P,2025-07-09,2026-02-20,,2035-07-10,2035-07-10,,89254021394215205955,639021391520595,,
865135061054548,James Onyango - KDU 613B,KDU 613B,automobile,KDU 613B,Probox,,James Onyango,,0790175997,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,X3,2025-07-09,2026-02-24,,2035-07-10,2035-07-10,,89254021394215205948,639021391520594,,
862798050526231,Rashid Hassan - KDM 840V,KDM 840V,automobile,KDM 840V,Probox,,Rashid Hassan,,0790175526,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2043-12-23,2043-12-23,,,,,
862798050523139,Mike Wanaswa - KDT 724R,KDT 724R,automobile,KDT 724R,Probox,,Mike Wanaswa,,0790175045,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2043-12-23,2043-12-23,,,,,
862798050523063,Kelvin Wambugu - KDR 594N,KDR 594N,automobile,KDR 594N,Probox,,Kelvin Wambugu,,0701211876,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2043-12-22,2043-12-22,,,,,
862798050523626,Major Simiyu - KDS 949Y,KDS 949Y,automobile,KDS 949Y,Probox,,Major Simiyu,,0701211892,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2033-12-23,2033-12-23,,,,,
862798050523337,Victor Kimutai - KDS 919Y,KDS 919Y,automobile,KDS 919Y,Probox,,Victor Kimutai,,0700242527,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2043-12-22,2043-12-22,,,,,
862798050523295,Emmanuel Luseno - KDS 453 Y,KDS 453 Y,automobile,KDS 453 Y,Pick-Up,,Emmanuel Luseno,,0700242474,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Telematics ,JC400P,2023-12-22,2026-02-20,,2033-12-23,2033-12-23,,,,,
862798050523014,Samuel Muriithy - KDR 594N,KDR 594N,automobile,KDR 594N,Probox,,Samuel Muriithy,,0790175423,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Telematics ,JC400P,2023-12-21,2026-02-20,,2033-12-22,2033-12-22,,,,,
862798050521521,John Kimeria - KDS 525D,KDS 525D,truck,KDS 525D,Crane,,John Kimeria,,0752958416,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Telematics ,JC400P,2023-11-26,2026-02-20,,2033-11-27,2033-11-27,,,,,
862798050524533,Leonard Nzai - KDM 306S,KDM 306S,automobile,KDM 306S,Probox,,Leonard Nzai,,0703487162,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2023-08-21,2026-02-20,,2033-08-22,2033-08-22,,,,,
359857082898016,Job Ngare - KDM 309S,KDM 309S,automobile,KDM 309S,Probox,,Job Ngare,,0706895756,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2023-08-15,2026-02-24,,2033-08-16,2033-08-16,,89254021324273007563,639021327300756,,
862798050525266,Dickson Jaoko - KDK 815R,KDK 815R,automobile,KDK 815R,Probox,,Dickson Jaoko,,0706665867,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,JC400P,2023-06-21,2026-02-20,,2033-06-22,2033-06-22,,,,,
862798050523527,Allan Owana - KDK 780K,KDK 780K,automobile,KDK 780K,Probox,,Allan Owana,,0792375024,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2022-12-03,2026-02-20,,2042-12-04,2042-12-04,,,,,
862798050524426,Amani Sulubu - KCY 090X,KCY 090X,automobile,KCY 090X,Probox,,Amani Sulubu,,0113823350,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2022-01-16,2026-02-20,,2042-01-17,2042-01-17,,,,,
862798050522065,Gideon Kiprono - KCQ 215F,KCQ 215F,automobile,KCQ 215F,Probox,,Gideon Kiprono,,0113343715,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2022-01-16,2026-02-20,,2042-01-17,2042-01-17,,,,,
862798050525670,Gabriel Musumba - KCE 690F,KCE 690F,automobile,KCE 690F,Probox,,Gabriel Musumba,,0701211996,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,JC400P,2022-01-15,2026-02-20,,2042-01-16,2042-01-16,,,,,
862798050288345,Santoes Omondi - KCZ 181P,KCZ 181P,automobile,KCZ 181P,Pick-Up,,Santoes Omondi,,0768446105,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,JC400P,2021-11-06,2026-02-20,,2041-11-07,2041-11-07,,,,,
862798050288303,Elias Baya - KCZ 476E,KCZ 476E,automobile,KCZ 476E,Probox,,Elias Baya,,0115870439,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,JC400P,2021-11-06,2026-02-20,,2041-11-07,2041-11-07,,,,,
862798050288212,Nicholas Erastus - KCQ 581M,KCQ 581M,automobile,KCQ 581M,Probox,,Nicholas Erastus,,0746979531,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,JC400P,2021-11-02,2026-02-20,,2041-11-03,2041-11-03,,,,,
359857082898008,Samuel Ng'ang'a - KDE 264M,KDE 264M,automobile,KDE 264M,Probox,,Samuel Ng'ang'a,,0711731539,,,,Dept: ISP,Default Group,ISP ,fireside,Fireside Telematics ,GT06E,2021-10-28,2026-02-24,,2041-10-29,2041-10-29,,89254021264260342245,639021266034224,,
359857082898487,Dan Watila - KDE 638J,KDE 638J,automobile,KDE 638J,Probox,,Dan Watila,,0116242996,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2021-10-21,2026-02-24,,2041-10-22,2041-10-22,,89254021334258404214,639021335840421,,
359857082900358,Geoffrey Too - KDM 308S,KDM 308S,automobile,KDM 308S,Probox,,Geoffrey Too,,0796527601,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,GT06E,2021-10-21,2026-02-24,,2041-10-22,2041-10-22,,89254021264260126572,639021266012657,,
359857082896911,Hamisi Pande - KDD 689Y,KDD 689Y,automobile,KDD 689Y,Probox,,Hamisi Pande,,0112714612,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2021-09-17,2026-02-24,,2041-09-18,2041-09-18,,89254021214211314660,639021211131466,,
359857082900697,George Ochieng' - KDD 684Y,KDD 684Y,automobile,KDD 684Y,Probox,,George Ochieng',,0114879518,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,GT06E,2021-09-17,2026-02-24,,2041-09-18,2041-09-18,,89254021214211314678,639021211131467,,
359857082897257,Cassius Wakiyo - KDB 323M,KDB 323M,automobile,KDB 323M,Probox,,Cassius Wakiyo,,0746428882,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,GT06E,2021-08-29,2026-02-24,,2041-08-29,2041-08-29,,89254021234222500818,639021232250081,,
359857082897737,John Makori - KDB 585E,KDB 585E,automobile,KDB 585E,Probox,,John Makori,,0114596734,,,,Dept: PLANNING,Default Group,PLANNING,fireside,Fireside Telematics ,GT06E,2021-08-29,2026-02-24,,2041-08-29,2041-08-29,,89254021214211145262,639021211114526,,
359857082911983,Brian Ngetich - KDA 717B,KDA 717B,automobile,KDA 717B,Probox,,Brian Ngetich,0795188807,0795188807,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2021-08-29,2026-02-24,,2041-08-29,2041-08-29,,89254021214211145288,639021211114528,,
359857082902461,Sadique Wakayula - KDC 490Q,KDC 490Q,truck,KDC 490Q,Crane,,Sadique Wakayula,,0757556468,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Telematics ,GT06E,2021-05-22,2026-02-24,,2041-05-22,2041-05-22,,89254021154296722488,639021159672248,,
359857082902503,Felix Andole - KDC 207R,KDC 207R,automobile,KDC 207R,Probox,,Felix Andole,,0794820817,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2021-05-15,2026-02-24,,2041-05-15,2041-05-15,,89254021224270993254,639021227099325,,
359857082897794,Mutuku Joseph - KDC 739F,KDC 739F,automobile,KDC 739F,Probox,,Mutuku Joseph,0115019037,0115019037,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,GT06E,2021-04-10,2026-02-24,,2041-04-10,2041-04-10,,89254021224222632356,639021222263235,,
359857082910589,Patric Bett - KDA 609E,KDA 609E,automobile,KDA 609E,Probox,,Patric Bett,,0797622637,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,GT06E,2020-10-26,2026-02-24,,2040-10-27,2040-10-27,,89254021154296722496,639021159672249,,
359857082918012,Charles Nyambane - KCB 711C,KCB 711C,automobile,KCB 711C,Probox,,Charles Nyambane,,0793704231,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2020-09-21,2026-02-24,,2040-09-22,2040-09-22,,89254021154287138363,639021158713836,,
359857081887069,Wright Oseko - KCG 668W,KCG 668W,automobile,KCG 668W,Probox,,Wright Oseko,,0746763106,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Telematics ,GT06E,2019-06-30,2026-02-24,,2039-07-01,2039-07-01,,89254021084186499915,639021088649991,,
359857081891590,Garage - KCE 699F,KCE 699F,automobile,KCE 699F,Probox,,Garage,,0746760215,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Telematics ,GT06E,2019-06-16,2026-02-24,,2039-06-17,2039-06-17,,89254021084186499519,639021088649951,,
359857081891566,Simon Kamau - KCE 090R,KCE 090R,automobile,KCE 090R,Probox,,Simon Kamau,,0746760404,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2019-06-16,2026-02-24,,2039-06-17,2039-06-17,,89254021084186499527,639021088649952,,
359857081892101,Cornelius Kimutai - KCU 938R,KCU 938R,automobile,KCU 938R,Van,,Cornelius Kimutai,,0746759919,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Telematics ,GT06E,2019-06-12,2026-02-24,,2039-06-13,2039-06-13,,89254021084186499451,639021088649945,,2019-06-12
359857081892309,Nicholas Erastus - KCQ 581M,KCQ 581M,automobile,KCQ 581M,Probox,,Nicholas Erastus,,0700023776,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Telematics ,GT06E,2019-06-09,2026-02-24,,2039-06-10,2039-06-10,,89254021084178504672,639021087850467,,
865135061563415,Barack Orwa - KDW 781E,KDW 781E,automobile,KDW 781E,Vazel,,Barack Orwa,,0758052541,,,,Dept: MGT,Default Group,MGT,fireside,Fireside Group MSA,X3,2026-01-13,2025-09-08,,2036-01-14,2036-01-14,,89254021414206816931,639021410681693,,
865135061035133,Major Simiyu - KDS 949Y,KDS 949Y,automobile,KDS 949Y,Probox,,Major Simiyu,,0768696642,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,X3,2025-08-02,2025-06-11,,2035-08-03,2035-08-03,,89254021394274518918,639021397451891,,
865135061043079,Mike Wanaswa - KDT 724R,KDT 724R,automobile,KDT 724R,Probox,,Mike Wanaswa,,0768696664,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,X3,2025-08-02,2025-06-11,,2035-08-03,2035-08-03,,89254021394274518959,639021397451895,,
865135061048953,Timothy Gitau - KDT 916R,KDT 916R,automobile,KDT 916R,Probox,,Timothy Gitau,,0768697056,,,,Dept: REGIONAL,Default Group,REGIONAL,fireside,Fireside Group MSA,X3,2025-08-02,2025-06-11,,2035-08-03,2035-08-03,,89254021394274518967,639021397451896,,
865135061048276,Victor Kimutai - KDS 919Y,KDS 919Y,automobile,KDS 919Y,Probox,,Victor Kimutai,,0768696755,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,X3,2025-08-02,2025-06-11,,2035-08-03,2035-08-03,,89254021394274518900,639021397451890,,
862798050526256,Ian Dancun - KDT 923R,KDT 923R,automobile,KDT 923R,Probox,,Ian Dancun,,0794873610,,,,Dept: QEHS,Default Group,QEHS,fireside,Fireside Group MSA,JC400P,2023-12-22,,,2043-12-22,2043-12-22,,,,,
862798050526165,Wilfred Kinyanjui - KCU 729C,KCU 729C,truck,KCU 729C,Crane,,Wilfred Kinyanjui,,0790564929,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Group MSA,JC400P,2023-11-26,2024-11-08,,2033-11-27,2033-11-27,,,,,
359857082916826,Denis Kazungu - KDM 794R,KDM 794R,automobile,KDM 794R,Probox,,Denis Kazungu,,0705700971,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,GT06E,2023-08-21,2023-08-22,,2033-08-22,2033-08-22,,89254021324273006854,639021327300685,,
359857082898073,Mutuku Antony - KDK 732K,KDK 732K,automobile,KDK 732K,Probox,,Mutuku Antony,,0793026954,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,GT06E,2022-12-20,2022-12-20,,2042-12-21,2042-12-21,,89254021234222387539,639021232238753,,
862798050524681,Mutuku Antony - KDK 732K,KDK 732K,automobile,KDK 732K,Probox,,Mutuku Antony,,0796275746,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,JC400P,2022-12-06,2022-12-16,,2042-12-07,2042-12-07,,,,,
862798050524566,Makanda Andrew - KCZ 155P,KCZ 155P,automobile,KCZ 155P,Pick-Up,,Makanda Andrew,,0758781444,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,JC400P,2022-01-22,2025-02-24,,2042-01-23,2042-01-23,,,,,
862798050521612,Denis Kazungu - KDM 794R,KDM 794R,automobile,KDM 794R,Probox,,Denis Kazungu,,0704113731,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,JC400P,2022-01-22,2024-11-19,,2042-01-23,2042-01-23,,,,,
862798050522719,Mbuvi Kioko - KCZ 199P,KCZ 199P,automobile,KCZ 199P,Pick-Up,,Mbuvi Kioko,,0768218655,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050524087,Felix Muema - KCZ 223P,KCZ 223P,automobile,KCZ 223P,Pick-Up,,Felix Muema,,0113973875,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,JC400P,2022-01-16,2024-12-30,,2042-01-17,2042-01-17,,,,,
862798050522891,Lawrence Kijogi - KCY 080X,KCY 080X,automobile,KCY 080X,Pick-Up,,Lawrence Kijogi,,0113287191,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050524392,Ndegwa Dancun - KCG 669W,KCG 669W,automobile,KCG 669W,Probox,,Ndegwa Dancun,,0113799173,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050521752,Simon Munda - KCZ 154S,KCZ 154S,automobile,KCZ 154S,Probox,,Simon Munda,,0113805921,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050524012,Moses Wambua - KCZ 751V,KCZ 751V,automobile,KCZ 751V,Probox,,Moses Wambua,,0113313797,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050523204,Amani Kazungu - KCY 084X,KCY 084X,automobile,KCY 084X,Probox,,Amani Kazungu,,0707892547,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050523949,Joseph Kabandi - KCY 076X,KCY 076X,automobile,KCY 076X,Probox,,Joseph Kabandi,,0113288492,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-16,,2042-01-17,2042-01-17,,,,,
862798050525613,Kennedy Chege - KCQ 618K,KCQ 618K,automobile,KCQ 618K,Probox,,Kennedy Chege,,0729994247,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,JC400P,2022-01-16,2022-12-19,,2042-01-17,2042-01-17,,,,,
862798050525753,Noel Merengeni - KCY 838X,KCY 838X,automobile,KCY 838X,Probox,,Noel Merengeni,,,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,JC400P,2022-01-15,2023-08-23,,2042-01-16,2042-01-16,,,,,
359857082925330,Noel Merengeni - KCY 838X,KCY 838X,automobile,KCY 838X,Probox,,Noel Merengeni,,0794873610,,,,Dept: FDS,Default Group,FDS,fireside,Fireside Group MSA,GT06E,2020-10-26,2023-08-22,,2040-10-27,2040-10-27,,89254021154296723429,639021159672342,,
359857082900341,Simon Munda - KCZ 154S,KCZ 154S,automobile,KCZ 154S,Probox,,Simon Munda,,0757236135,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-09-23,2022-12-16,,2040-09-24,2040-09-24,,89254021154296723312,639021159672331,,
359857082912486,Moses Wambua - KCZ 751V,KCZ 751V,automobile,KCZ 751V,Probox,,Moses Wambua,,0792756503,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-09-23,2022-12-16,,2040-09-24,2040-09-24,,89254021154296723437,639021159672343,,
353549090553685,Daniel Omondi - KMFF 099Z,KMFF 099Z,mtc,KMFF 099Z,Motorbike,,Daniel Omondi,0112794067,0759336150,,,,Dept: OSP-PATROL,Default Group,OSP-PATROL,fireside,Fireside Group MSA,AT4,2020-09-23,2022-12-16,,2040-09-24,2040-09-24,,89254021334258404099,639021335840409,,
353549090567685,Daniel Kipkirui - KMFF 162Z,KMFF 162Z,mtc,KMFF 162Z,Motorbike,,Daniel Kipkirui,0112795498,0742532058,,,,Dept: OSP-PATROL,Default Group,OSP-PATROL,fireside,Fireside Group MSA,AT4,2020-09-23,2022-12-16,,2040-09-24,2040-09-24,,89254021264260388966,639021266038896,,
359857082910886,Makanda Andrew - KCZ 155P,KCZ 155P,automobile,KCZ 155P,Pick-Up,,Makanda Andrew,,0745067338,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2020-08-23,2025-02-24,,2040-08-24,2040-08-24,,89254021154287138397,639021158713839,,
359857082908500,Santoes Omondi - KCZ 181P,KCZ 181P,automobile,KCZ 181P,Pick-Up,,Santoes Omondi,,0701211974,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2020-08-23,2022-12-16,,2040-08-24,2040-08-24,,89254021374215155087,639021371515508,,
359857082918038,Mbuvi Kioko - KCC 199P,KCC 199P,automobile,KCC 199P,Pick-Up,,Mbuvi Kioko,,0797318126,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2020-08-22,2022-12-16,,2040-08-23,2040-08-23,,89254021154287138389,639021158713838,,
359857082907973,Felix Muema - KCZ 223P,KCZ 223P,automobile,KCZ 223P,Probox,,Felix Muema,,0757843826,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2020-08-22,2024-12-30,,2040-08-23,2040-08-23,,89254021154287138371,639021158713837,,
359857082042854,Elias Baya - KCZ 476E,KCZ 476E,automobile,KCZ 476E,Probox,,Elias Baya,,0110941187,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-08-09,2022-12-16,,2040-08-10,2040-08-10,,89254021164224352993,639021162435299,,
359857082044280,Lawrence Kijogi - KCY 080X,KCY 080X,automobile,KCY 080X,Probox,,Lawrence Kijogi,,0708155933,,,,Dept: ROLLOUT,Default Group,ROLLOUT,fireside,Fireside Group MSA,GT06E,2020-07-13,2022-12-16,,2040-07-13,2040-07-13,,89254029851005131222,639029850513122,,
359857082037185,Amani Kazungu - KCY 084X,KCY 084X,automobile,KCY 084X,Probox,,Amani Kazungu,,0757338522,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-07-13,2022-12-16,,2040-07-14,2040-07-14,,89254021154287000597,639021158700059,,
359857082046145,Joseph Kabandi - KCY 076X,KCY 076X,automobile,KCY 076X,Probox,,Joseph Kabandi,,0110850007,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-07-13,2022-12-16,,2040-07-14,2040-07-14,,89254021164223447158,639021162344715,,
359857082040981,Amani Sulubu - KCY 090X,KCY 090X,automobile,KCY 090X,Probox,,Amani Sulubu,,0793375853,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2020-07-13,2022-12-16,,2040-07-14,2040-07-14,,89254021064168004164,639021066800416,,
359857082038977,Wilfred Kinyanjui - KCU 729C,KCU 729C,truck,KCU 729C,Crane,,Wilfred Kinyanjui,,0110094469,,,,Dept: GENERAL,Default Group,GENERAL,fireside,Fireside Group MSA,GT06E,2020-04-05,2022-12-16,,2040-04-06,2040-04-06,,89254021164215938057,639021161593805,,
359857081886467,Gideon Kiprono - KCQ 215F,KCQ 215F,automobile,KCQ 215F,Probox,,Gideon Kiprono,,0746763076,,,,Dept: ISP,Default Group,ISP,fireside,Fireside Group MSA,GT06E,2019-06-30,2022-12-16,,2039-07-01,2039-07-01,,89254021084186499865,639021088649986,,
359857081886905,Kennedy Chege - KCQ 618K,KCQ 618K,automobile,KCQ 618K,Probox,,Kennedy Chege,,0746763132,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2019-06-30,2022-12-16,,2039-07-01,2039-07-01,,89254021084186499923,639021088649992,,
359857081887192,Ndegwa Dancun - KCG 669W,KCG 669W,automobile,KCG 669W,Probox,,Ndegwa Dancun,,0746760191,,,,Dept: OSP,Default Group,OSP,fireside,Fireside Group MSA,GT06E,2019-06-15,2022-12-16,,2039-06-16,2039-06-16,,89254021084186499501,639021088649950,,
1 IMEI Device Name Vehicle Name Vehicle Icon License Plate No. Vehicle Model Vehicle Brand Driver Name Telephone SIM Fuel/100km VIN Engine Number Remarks Group Department Account Customer Name Model Activated Date Sales Time MAC Subscription Expiration User Expiration Date Battery replacement date ICCID IMSI ID Number Installation Time
2 865135061569479 UMA 382EK UMA 382EK automobile UMA 382EK UG +256792997079 Dept: MTN Default Group MTN fireside Fireside Group HQ X3 2026-02-26 2025-09-08 2036-02-27 2036-02-27 8925610001837573419F 641101970467667
3 865135061569131 UMA 418EK UMA 418EK automobile UMA 418EK UG +256792997053 Dept: MTN Default Group MTN fireside Fireside Group HQ X3 2026-02-26 2025-09-08 2036-02-27 2036-02-27 8925610001837573385F 641101970467664
4 862798052707896 John Mbugua - KDW 573B KDW 573B automobile KDW 573B Probox John Mbugua Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2026-01-30 2025-06-11 2036-01-31 2036-01-31 89254021414206816725 639021410681672
5 865135061563423 Joel Ntumba - UMA 826AB UMA 826AB mtc UMA 826AB Motorbike Joel Ntumba 0119051036 Dept: MTN Default Group MTN fireside Fireside Group HQ X3 2026-01-28 2025-09-08 2036-01-29 2036-01-29 89254021414206652690 639021410665269
6 865135061564280 Rodin Kiberu - UMA 011EK UMA 011EK mtc UMA 011EK Motorbike Rodin Kiberu 0118081642 Dept: MTN Default Group MTN fireside Fireside Group HQ X3 2026-01-28 2025-09-08 2036-01-29 2036-01-29 89254021414206817244 639021410681724
7 862798052708068 Dominic Wambua - KDV 683Z KDV 683Z automobile KDV 683Z Probox Dominic Wambua 0758048043 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Group HQ JC400P 2026-01-24 2025-06-11 2036-01-25 2036-01-25 89254021414206816964 639021410681696
8 862798052708167 Levine Wasike - KDV 439W KDV 439W automobile KDV 439W Probox Levine Wasike 0758046738 Dept: FDS Default Group FDS fireside Fireside Group HQ JC400P 2025-12-13 2025-06-11 2035-12-14 2035-12-14 89254021414206816741 639021410681674
9 865135061563639 Benjamin Ananda - KDV 438W KDV 438W automobile KDV 438W Probox Benjamin Ananda 0758047065 Dept: PLANNING Default Group PLANNING fireside Fireside Group HQ X3 2025-12-13 2025-09-08 2035-12-14 2035-12-14 89254021414206816683 639021410681668
10 865135061569123 Albert Mutwiri - KDV 437W KDV 437W automobile KDV 437W Probox Albert Mutwiri 0758047101 Dept: FDS Default Group FDS fireside Fireside Group HQ X3 2025-12-13 2025-09-08 2035-12-14 2035-12-14 89254021414206816881 639021410681688
11 865135061564470 Silvanus Kipkorir - KDV 064S KDV 064S automobile KDV 064S Probox Silvanus Kipkorir 0113669866 Dept: AIRTEL Default Group AIRTEL fireside Fireside Group HQ X3 2025-11-21 2025-09-08 2035-11-22 2035-11-22 89254021414206378718 639021410637871
12 865135061581904 Robert Kipruto - KDV 072L KDV 072L automobile KDV 072L Probox Robert Kipruto 0114149576 Dept: FDS Default Group FDS fireside Fireside Group HQ X3 2025-11-21 2025-09-08 2035-11-22 2035-11-22 89254021264261503993 639021266150399
13 862798052713779 Benard Kimutai - KDN 759G KDN 759G automobile KDN 759G Probox Benard Kimutai 0752143258 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2025-08-23 2025-06-11 2035-08-24 2035-08-24 89254035061001753860 639035060175386
14 865135061043426 Geoffrey Karanja - KMGS 239H KMGS 239H mtc KMGS 239H Motorbike Geoffrey Karanja 0768696658 Dept: OSP-PATROL Default Group OSP-PATROL fireside Fireside Group HQ X3 2025-08-22 2025-06-11 2035-08-23 2035-08-23 89254021394274518926 639021397451892
15 865135061053714 Samuel Kihara - KMEL 225X KMEL 225X mtc KMEL 225X Motorbike Samuel Kihara 0768696832 Dept: OSP-PATROL Default Group OSP-PATROL fireside Fireside Group HQ X3 2025-08-02 2025-06-11 2035-08-03 2035-08-03 89254021394274518934 639021397451893
16 865135061036164 Brian Njenga - KMFF 113Z KMFF 113Z mtc KMFF 113Z Motorbike Brian Njenga 0768696705 Dept: OSP-PATROL Default Group OSP-PATROL fireside Fireside Group HQ X3 2025-07-31 2025-06-11 2035-08-01 2035-08-01 89254021394274518850 639021397451885
17 865135061049001 Parked - KMGK 596V KMGK 596V mtc KMGK 596V Motorbike Parked 0768697064 Dept: DELIVERIES Default Group DELIVERIES fireside Fireside Group HQ X3 2025-07-31 2025-06-11 2035-08-01 2035-08-01 89254021394274518884 639021397451888
18 862798052715220 Rofas Njagi - KDT 728R KDT 728R automobile KDT 728R Probox Rofas Njagi 0704573658 Dept: REGIONAL Default Group REGIONAL fireside Fireside Group HQ JC400P 2025-07-16 2025-06-11 2035-07-17 2035-07-17 89254021334258495873 639021335849587
19 865135061037980 Emmanuel Luseno - KDS 453Y KDS 453Y automobile KDS 453Y Pick-Up Emmanuel Luseno 0790176734 Dept: GENERAL Default Group GENERAL fireside Fireside Group HQ X3 2025-07-15 2025-06-11 2035-07-15 89254021394215205856 639021391520585
20 865135061035778 John Kimeria - KDS 525D KDS 525D truck KDS 525D Crane John Kimeria 0790176738 Dept: GENERAL Default Group GENERAL fireside Fireside Group HQ X3 2025-07-11 2025-06-11 2035-07-12 2035-07-12 89254021394215205922 639021391520592
21 865135061053748 Rashid Hassan - KDM 840V KDM 840V automobile KDM 840V Probox Rashid Hassan 0768445963 Dept: ISP Default Group ISP fireside Fireside Group HQ X3 2025-07-10 2025-06-11 2035-07-11 2035-07-11 89254021334212352574 639021331235257
22 865135061042261 Kelvin Wambugu - KDR 592N KDR 592N automobile KDR 592N Probox Kelvin Wambugu 0797680464 Dept: FDS Default Group FDS fireside Fireside Group HQ X3 2025-07-10 2025-06-11 2035-07-11 2035-07-11 89254021334258159693 639021335815969
23 862798052713811 James Onyango - KDU 613B KDU 613B automobile KDU 613B Probox James Onyango 0790176542 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2025-07-09 2025-06-11 2035-07-10 2035-07-10 89254021394215205880 639021391520588
24 865135061047435 Management_Mazda - KDU 613A KDU 613A automobile KDU 613A Mazda Management_Mazda 0790175971 Dept: MGT Default Group MGT fireside Fireside Group HQ X3 2025-07-09 2025-06-11 2035-07-10 2035-07-10 89254021394215205971 639021391520597
25 862798050522743 Charles Nyambane - KCB 711C KCB 711C automobile KCB 711C Probox Charles Nyambane 0768657106 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2023-12-22 2024-11-08 2033-12-23 2033-12-23
26 862798050525225 Sadique Wakayula - KDC 490Q KDC 490Q truck KDC 490Q Crane Sadique Wakayula 0768652386 Dept: GENERAL Default Group GENERAL fireside Fireside Group HQ JC400P 2023-12-22 2024-11-08 2043-12-22 2043-12-22
27 862798050525068 Samuel Ng'ang'a - KDE 264M KDE 264M automobile KDE 264M Probox Samuel Ng'ang'a 0768658564 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2023-12-22 2024-11-08 2033-12-23 2033-12-23
28 862798050525837 Kennedy Ondieki - KCU 237Z KCU 237Z automobile KCU 237Z Probox Kennedy Ondieki 0113669852 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2023-12-21 2033-12-22 2033-12-22
29 862798050523618 Geoffrey Too - KDM 308S KDM 308S automobile KDM 308S Probox Geoffrey Too 0701211625 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2023-08-15 2023-08-22 2033-08-16 2033-08-16
30 862798050523816 Job Ngare - KDM 309S KDM 309S automobile KDM 309S Probox Job Ngare 0707936781 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2023-08-15 2023-08-22 2033-08-16 2033-08-16
31 359857082912239 Dickson Jaoko - KDK 815R KDK 815R automobile KDK 815R Probox Dickson Jaoko 0706392117 Dept: OSP Default Group OSP fireside Fireside Group HQ GT06E 2023-06-21 2023-07-27 2033-06-22 2033-06-22 89254021234296021287 639021239602128
32 359857082897091 Peter Mbugua - KDK 728K KDK 728K automobile KDK 728K Probox Peter Mbugua 0790262984 Dept: ISP Default Group ISP fireside Fireside Group HQ GT06E 2022-12-14 2022-12-16 2042-12-15 2042-12-15 89254021234222500396 639021232250039
33 862798050524608 Peter Mbugua - KDK 728K KDK 728K automobile KDK 728K Probox Peter Mbugua 0706742413 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-12-03 2022-12-15 2042-12-04 2042-12-04
34 862798050524368 862798050524368 automobile Default Group fireside Fireside Group HQ JC400P 2022-10-29 2022-12-17 2042-10-30 2042-10-30
35 862798050524558 Mutuku Joseph - KDC 739F KDC 739F automobile KDC 739F Probox Mutuku Joseph 0100858817 Dept: FDS Default Group FDS fireside Fireside Group HQ JC400P 2022-01-22 2022-01-25 2042-01-23 2042-01-23
36 862798050524897 Cornelius Kimutai - KCU 938R KCU 938R automobile KCU 938R Van Cornelius Kimutai 0114924404 Dept: FDS Default Group FDS fireside Fireside Group HQ JC400P 2022-01-22 2022-01-25 2042-01-23 2042-01-23
37 862798050522107 Cassius Wakiyo - KDB 323M KDB 323M automobile KDB 323M Probox Cassius Wakiyo 0114149576 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2022-01-22 2022-01-25 2042-01-23 2042-01-23
38 862798050524657 Felix Andole - KDC 207R KDC 207R automobile KDC 207R Probox Felix Andole 0758689195 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-01-22 2022-01-25 2042-01-23 2042-01-23
39 862798050523386 George Ochieng' - KDD 684Y KDD 684Y automobile KDD 684Y Probox George Ochieng' 0785586834 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2022-01-22 2022-01-27 2042-01-23 2042-01-23
40 862798050524384 Hamisi Pande - KDD 689Y KDD 689Y automobile KDD 689Y Probox Hamisi Pande 0701211744 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-01-22 2022-01-27 2042-01-23 2042-01-23
41 862798050525589 Simon Kamau - KCE 090R KCE 090R automobile KCE 090R Probox Simon Kamau 0796276387 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-01-19 2022-01-17 2042-01-20 2042-01-20
42 862798050525423 Makori John - KDB 585E KDB 585E automobile KDB 585E Probox Makori John 0701211724 Dept: PLANNING Default Group PLANNING fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
43 862798050525951 Wright Oseko - KCG 668W KCG 668W automobile KCG 668W Probox Wright Oseko 0741943212 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
44 862798050522859 Garage - KCH 167M KCH 167M automobile KCH 167M Probox Garage 0706740252 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
45 862798050524707 Garage - KCE 699F KCE 699F automobile KCE 699F Probox Garage 0110525751 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
46 862798050522883 Dan Watila - KDE 638J KDE 638J automobile KDE 638J Probox Dan Watila 0112615393 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
47 862798050525605 John Ondego - KCA 542Q KCA 542Q automobile KCA 542Q Probox John Ondego 0110526783 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2022-01-15 2022-01-17 2042-01-16 2042-01-16
48 862798050288360 Brian Ngetich - KDA 717B KDA 717B automobile KDA 717B Probox Brian Ngetich 0717867861 Dept: ISP Default Group ISP fireside Fireside Group HQ JC400P 2021-11-05 2021-11-08 2041-11-06 2041-11-06
49 862798050288261 Patric Bett - KDA 609E KDA 609E automobile KDA 609E Probox Patric Bett 0112693340 0790176509 Dept: OSP Default Group OSP fireside Fireside Group HQ JC400P 2021-10-23 2021-10-25 2041-10-24 2041-10-24
50 359857082042052 Gabriel Musumba - KCE 690F KCE 690F automobile KCE 690F Probox Gabriel Musumba 0110094466 Dept: OSP Default Group OSP fireside Fireside Group HQ GT06E 2020-04-03 2020-04-16 2040-04-04 2040-04-04 89254021164215938024 639021161593802
51 359857081885410 Allan Owana - KDK 780K KDK 780K automobile KDK 780K Probox Allan Owana 0703616117 Dept: ISP Default Group ISP fireside Fireside Group HQ GT06E 2019-06-19 2019-07-01 2039-06-20 2039-06-20 89254021234222499854 639021232249985
52 359857081891798 Garage - KCH 167M KCH 167M automobile KCH 167M Probox Garage 0746760102 Dept: OSP Default Group OSP fireside Fireside Group HQ GT06E 2019-06-16 2019-07-01 2039-06-17 2039-06-17 89254021084186499493 639021088649949
53 359857081891632 John Ondego - KCA 542Q KCA 542Q automobile KCA 542Q Probox John Ondego 0746760038 Dept: ISP Default Group ISP fireside Fireside Group HQ GT06E 2019-06-15 2019-07-01 2039-06-16 2039-06-16 89254021084186499485 639021088649948
54 862798052708035 862798052708035 automobile Probox Default Group fireside Fireside Group HQ JC400P Inactive 2025-06-11 120Month ——
55 865135061563597 Dominic Wambua - KDV 683Z KDV 683Z automobile KDV 683Z Probox Dominic Wambua 0758052405 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Telematics X3 2026-01-30 2026-02-24 2036-01-31 2036-01-31 89254021414206816733 639021410681673
56 865135061562722 John Mbugua - KDW 573B KDW 573B automobile KDW 573B Probox John Mbugua 0758052508 Dept: OSP Default Group OSP fireside Fireside Telematics X3 2026-01-30 2026-02-24 2036-01-31 2036-01-31 89254021414206816832 639021410681683
57 862798052708282 Godffrey Nandwa - KCN 496A KCN 496A automobile KCN 496A Probox Godffrey Nandwa 0758047934 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2026-01-25 2026-02-20 2036-01-26 2036-01-26 89254021414206816865 639021410681686
58 862798052707888 Benjamin Ananda - KDV 438W KDV 438W automobile KDV 438W Probox Benjamin Ananda 0758047312 Dept: PLANNING Default Group PLANNING fireside Fireside Telematics JC400P 2025-12-15 2026-02-20 2035-12-16 2035-12-16 89254021414206816980 639021410681698
59 862798052708076 Albert Mutwiri - KDV 437W KDV 437W automobile KDV 437W Probox Albert Mutwiri 0758047094 Dept: FDS Default Group FDS fireside Fireside Telematics JC400P 2025-12-13 2026-02-20 2035-12-14 2035-12-14 89254021414206816782 639021410681678
60 865135061562847 Levine Wasike - KDV 439W KDV 439W automobile KDV 439W Probox Levine Wasike 0758047032 Dept: OSP Default Group OSP fireside Fireside Telematics X3 2025-12-13 2026-02-24 2035-12-14 2035-12-14 89254021414206816840 639021410681684
61 862798052714066 862798052714066 automobile Probox Default Group fireside Fireside Telematics JC400P 2025-11-21 2025-06-11 2035-11-22 2035-11-22 89254021414206378684 639021410637868
62 862798052713837 Kennedy Ondieki - KCU 237Z KCU 237Z automobile KCU 237Z Probox Kennedy Ondieki 0113669852 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2025-10-08 2026-02-20 2035-10-09 2035-10-09 89254021414206327855 639021410632785
63 862798052713696 862798052713696 automobile Probox Default Group fireside Fireside Telematics JC400P 2025-09-02 2025-06-11 2035-09-03 2035-09-03 89254021394215205906 639021391520590
64 862798052713985 Timothy Gitau - KDT 916R KDT 916R automobile KDT 916R Probox Timothy Gitau 0768696668 Dept: REGIONAL Default Group REGIONAL fireside Fireside Telematics JC400P 2025-08-02 2026-02-20 2035-08-03 2035-08-03 89254021394274518892 639021397451889
65 865135061035653 Richardson Komu - KDT 923R KDT 923R automobile KDT 923R Probox Richardson Komu 0768697292 Dept: ISP Default Group ISP fireside Fireside Telematics X3 2025-08-02 2026-02-24 2035-08-03 2035-08-03 89254021394274518942 639021397451894
66 865135061048466 Samuel Muriithy - KDR 594N KDR 594N automobile KDR 594N Probox Samuel Muriithy 0797680395 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Telematics X3 2025-07-24 2026-02-24 2035-07-25 2035-07-25 89254021334258159628 639021335815962
67 865135061054555 Rofas Njagi - KDT 728R KDT 728R automobile KDT 728R Probox Rofas Njagi 0790176726 Dept: REGIONAL Default Group REGIONAL fireside Fireside Telematics X3 2025-07-16 2026-02-24 2035-07-17 2035-07-17 89254021394215205823 639021391520582
68 862798052713761 Management_Mazda - KDU 613A KDU 613A automobile KDU 613A Mazda Management_Mazda 0790176786 Dept: MGT Default Group MGT fireside Fireside Telematics JC400P 2025-07-09 2026-02-20 2035-07-10 2035-07-10 89254021394215205955 639021391520595
69 865135061054548 James Onyango - KDU 613B KDU 613B automobile KDU 613B Probox James Onyango 0790175997 Dept: ISP Default Group ISP fireside Fireside Telematics X3 2025-07-09 2026-02-24 2035-07-10 2035-07-10 89254021394215205948 639021391520594
70 862798050526231 Rashid Hassan - KDM 840V KDM 840V automobile KDM 840V Probox Rashid Hassan 0790175526 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2043-12-23 2043-12-23
71 862798050523139 Mike Wanaswa - KDT 724R KDT 724R automobile KDT 724R Probox Mike Wanaswa 0790175045 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2043-12-23 2043-12-23
72 862798050523063 Kelvin Wambugu - KDR 594N KDR 594N automobile KDR 594N Probox Kelvin Wambugu 0701211876 Dept: FDS Default Group FDS fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2043-12-22 2043-12-22
73 862798050523626 Major Simiyu - KDS 949Y KDS 949Y automobile KDS 949Y Probox Major Simiyu 0701211892 Dept: FDS Default Group FDS fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2033-12-23 2033-12-23
74 862798050523337 Victor Kimutai - KDS 919Y KDS 919Y automobile KDS 919Y Probox Victor Kimutai 0700242527 Dept: OSP Default Group OSP fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2043-12-22 2043-12-22
75 862798050523295 Emmanuel Luseno - KDS 453 Y KDS 453 Y automobile KDS 453 Y Pick-Up Emmanuel Luseno 0700242474 Dept: GENERAL Default Group GENERAL fireside Fireside Telematics JC400P 2023-12-22 2026-02-20 2033-12-23 2033-12-23
76 862798050523014 Samuel Muriithy - KDR 594N KDR 594N automobile KDR 594N Probox Samuel Muriithy 0790175423 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Telematics JC400P 2023-12-21 2026-02-20 2033-12-22 2033-12-22
77 862798050521521 John Kimeria - KDS 525D KDS 525D truck KDS 525D Crane John Kimeria 0752958416 Dept: GENERAL Default Group GENERAL fireside Fireside Telematics JC400P 2023-11-26 2026-02-20 2033-11-27 2033-11-27
78 862798050524533 Leonard Nzai - KDM 306S KDM 306S automobile KDM 306S Probox Leonard Nzai 0703487162 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2023-08-21 2026-02-20 2033-08-22 2033-08-22
79 359857082898016 Job Ngare - KDM 309S KDM 309S automobile KDM 309S Probox Job Ngare 0706895756 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2023-08-15 2026-02-24 2033-08-16 2033-08-16 89254021324273007563 639021327300756
80 862798050525266 Dickson Jaoko - KDK 815R KDK 815R automobile KDK 815R Probox Dickson Jaoko 0706665867 Dept: OSP Default Group OSP fireside Fireside Telematics JC400P 2023-06-21 2026-02-20 2033-06-22 2033-06-22
81 862798050523527 Allan Owana - KDK 780K KDK 780K automobile KDK 780K Probox Allan Owana 0792375024 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2022-12-03 2026-02-20 2042-12-04 2042-12-04
82 862798050524426 Amani Sulubu - KCY 090X KCY 090X automobile KCY 090X Probox Amani Sulubu 0113823350 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2022-01-16 2026-02-20 2042-01-17 2042-01-17
83 862798050522065 Gideon Kiprono - KCQ 215F KCQ 215F automobile KCQ 215F Probox Gideon Kiprono 0113343715 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2022-01-16 2026-02-20 2042-01-17 2042-01-17
84 862798050525670 Gabriel Musumba - KCE 690F KCE 690F automobile KCE 690F Probox Gabriel Musumba 0701211996 Dept: OSP Default Group OSP fireside Fireside Telematics JC400P 2022-01-15 2026-02-20 2042-01-16 2042-01-16
85 862798050288345 Santoes Omondi - KCZ 181P KCZ 181P automobile KCZ 181P Pick-Up Santoes Omondi 0768446105 Dept: OSP Default Group OSP fireside Fireside Telematics JC400P 2021-11-06 2026-02-20 2041-11-07 2041-11-07
86 862798050288303 Elias Baya - KCZ 476E KCZ 476E automobile KCZ 476E Probox Elias Baya 0115870439 Dept: FDS Default Group FDS fireside Fireside Telematics JC400P 2021-11-06 2026-02-20 2041-11-07 2041-11-07
87 862798050288212 Nicholas Erastus - KCQ 581M KCQ 581M automobile KCQ 581M Probox Nicholas Erastus 0746979531 Dept: ISP Default Group ISP fireside Fireside Telematics JC400P 2021-11-02 2026-02-20 2041-11-03 2041-11-03
88 359857082898008 Samuel Ng'ang'a - KDE 264M KDE 264M automobile KDE 264M Probox Samuel Ng'ang'a 0711731539 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2021-10-28 2026-02-24 2041-10-29 2041-10-29 89254021264260342245 639021266034224
89 359857082898487 Dan Watila - KDE 638J KDE 638J automobile KDE 638J Probox Dan Watila 0116242996 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2021-10-21 2026-02-24 2041-10-22 2041-10-22 89254021334258404214 639021335840421
90 359857082900358 Geoffrey Too - KDM 308S KDM 308S automobile KDM 308S Probox Geoffrey Too 0796527601 Dept: OSP Default Group OSP fireside Fireside Telematics GT06E 2021-10-21 2026-02-24 2041-10-22 2041-10-22 89254021264260126572 639021266012657
91 359857082896911 Hamisi Pande - KDD 689Y KDD 689Y automobile KDD 689Y Probox Hamisi Pande 0112714612 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2021-09-17 2026-02-24 2041-09-18 2041-09-18 89254021214211314660 639021211131466
92 359857082900697 George Ochieng' - KDD 684Y KDD 684Y automobile KDD 684Y Probox George Ochieng' 0114879518 Dept: OSP Default Group OSP fireside Fireside Telematics GT06E 2021-09-17 2026-02-24 2041-09-18 2041-09-18 89254021214211314678 639021211131467
93 359857082897257 Cassius Wakiyo - KDB 323M KDB 323M automobile KDB 323M Probox Cassius Wakiyo 0746428882 Dept: OSP Default Group OSP fireside Fireside Telematics GT06E 2021-08-29 2026-02-24 2041-08-29 2041-08-29 89254021234222500818 639021232250081
94 359857082897737 John Makori - KDB 585E KDB 585E automobile KDB 585E Probox John Makori 0114596734 Dept: PLANNING Default Group PLANNING fireside Fireside Telematics GT06E 2021-08-29 2026-02-24 2041-08-29 2041-08-29 89254021214211145262 639021211114526
95 359857082911983 Brian Ngetich - KDA 717B KDA 717B automobile KDA 717B Probox Brian Ngetich 0795188807 0795188807 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2021-08-29 2026-02-24 2041-08-29 2041-08-29 89254021214211145288 639021211114528
96 359857082902461 Sadique Wakayula - KDC 490Q KDC 490Q truck KDC 490Q Crane Sadique Wakayula 0757556468 Dept: GENERAL Default Group GENERAL fireside Fireside Telematics GT06E 2021-05-22 2026-02-24 2041-05-22 2041-05-22 89254021154296722488 639021159672248
97 359857082902503 Felix Andole - KDC 207R KDC 207R automobile KDC 207R Probox Felix Andole 0794820817 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2021-05-15 2026-02-24 2041-05-15 2041-05-15 89254021224270993254 639021227099325
98 359857082897794 Mutuku Joseph - KDC 739F KDC 739F automobile KDC 739F Probox Mutuku Joseph 0115019037 0115019037 Dept: FDS Default Group FDS fireside Fireside Telematics GT06E 2021-04-10 2026-02-24 2041-04-10 2041-04-10 89254021224222632356 639021222263235
99 359857082910589 Patric Bett - KDA 609E KDA 609E automobile KDA 609E Probox Patric Bett 0797622637 Dept: OSP Default Group OSP fireside Fireside Telematics GT06E 2020-10-26 2026-02-24 2040-10-27 2040-10-27 89254021154296722496 639021159672249
100 359857082918012 Charles Nyambane - KCB 711C KCB 711C automobile KCB 711C Probox Charles Nyambane 0793704231 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2020-09-21 2026-02-24 2040-09-22 2040-09-22 89254021154287138363 639021158713836
101 359857081887069 Wright Oseko - KCG 668W KCG 668W automobile KCG 668W Probox Wright Oseko 0746763106 Dept: OSP Default Group OSP fireside Fireside Telematics GT06E 2019-06-30 2026-02-24 2039-07-01 2039-07-01 89254021084186499915 639021088649991
102 359857081891590 Garage - KCE 699F KCE 699F automobile KCE 699F Probox Garage 0746760215 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Telematics GT06E 2019-06-16 2026-02-24 2039-06-17 2039-06-17 89254021084186499519 639021088649951
103 359857081891566 Simon Kamau - KCE 090R KCE 090R automobile KCE 090R Probox Simon Kamau 0746760404 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2019-06-16 2026-02-24 2039-06-17 2039-06-17 89254021084186499527 639021088649952
104 359857081892101 Cornelius Kimutai - KCU 938R KCU 938R automobile KCU 938R Van Cornelius Kimutai 0746759919 Dept: FDS Default Group FDS fireside Fireside Telematics GT06E 2019-06-12 2026-02-24 2039-06-13 2039-06-13 89254021084186499451 639021088649945 2019-06-12
105 359857081892309 Nicholas Erastus - KCQ 581M KCQ 581M automobile KCQ 581M Probox Nicholas Erastus 0700023776 Dept: ISP Default Group ISP fireside Fireside Telematics GT06E 2019-06-09 2026-02-24 2039-06-10 2039-06-10 89254021084178504672 639021087850467
106 865135061563415 Barack Orwa - KDW 781E KDW 781E automobile KDW 781E Vazel Barack Orwa 0758052541 Dept: MGT Default Group MGT fireside Fireside Group MSA X3 2026-01-13 2025-09-08 2036-01-14 2036-01-14 89254021414206816931 639021410681693
107 865135061035133 Major Simiyu - KDS 949Y KDS 949Y automobile KDS 949Y Probox Major Simiyu 0768696642 Dept: FDS Default Group FDS fireside Fireside Group MSA X3 2025-08-02 2025-06-11 2035-08-03 2035-08-03 89254021394274518918 639021397451891
108 865135061043079 Mike Wanaswa - KDT 724R KDT 724R automobile KDT 724R Probox Mike Wanaswa 0768696664 Dept: ISP Default Group ISP fireside Fireside Group MSA X3 2025-08-02 2025-06-11 2035-08-03 2035-08-03 89254021394274518959 639021397451895
109 865135061048953 Timothy Gitau - KDT 916R KDT 916R automobile KDT 916R Probox Timothy Gitau 0768697056 Dept: REGIONAL Default Group REGIONAL fireside Fireside Group MSA X3 2025-08-02 2025-06-11 2035-08-03 2035-08-03 89254021394274518967 639021397451896
110 865135061048276 Victor Kimutai - KDS 919Y KDS 919Y automobile KDS 919Y Probox Victor Kimutai 0768696755 Dept: OSP Default Group OSP fireside Fireside Group MSA X3 2025-08-02 2025-06-11 2035-08-03 2035-08-03 89254021394274518900 639021397451890
111 862798050526256 Ian Dancun - KDT 923R KDT 923R automobile KDT 923R Probox Ian Dancun 0794873610 Dept: QEHS Default Group QEHS fireside Fireside Group MSA JC400P 2023-12-22 2043-12-22 2043-12-22
112 862798050526165 Wilfred Kinyanjui - KCU 729C KCU 729C truck KCU 729C Crane Wilfred Kinyanjui 0790564929 Dept: GENERAL Default Group GENERAL fireside Fireside Group MSA JC400P 2023-11-26 2024-11-08 2033-11-27 2033-11-27
113 359857082916826 Denis Kazungu - KDM 794R KDM 794R automobile KDM 794R Probox Denis Kazungu 0705700971 Dept: FDS Default Group FDS fireside Fireside Group MSA GT06E 2023-08-21 2023-08-22 2033-08-22 2033-08-22 89254021324273006854 639021327300685
114 359857082898073 Mutuku Antony - KDK 732K KDK 732K automobile KDK 732K Probox Mutuku Antony 0793026954 Dept: FDS Default Group FDS fireside Fireside Group MSA GT06E 2022-12-20 2022-12-20 2042-12-21 2042-12-21 89254021234222387539 639021232238753
115 862798050524681 Mutuku Antony - KDK 732K KDK 732K automobile KDK 732K Probox Mutuku Antony 0796275746 Dept: FDS Default Group FDS fireside Fireside Group MSA JC400P 2022-12-06 2022-12-16 2042-12-07 2042-12-07
116 862798050524566 Makanda Andrew - KCZ 155P KCZ 155P automobile KCZ 155P Pick-Up Makanda Andrew 0758781444 Dept: OSP Default Group OSP fireside Fireside Group MSA JC400P 2022-01-22 2025-02-24 2042-01-23 2042-01-23
117 862798050521612 Denis Kazungu - KDM 794R KDM 794R automobile KDM 794R Probox Denis Kazungu 0704113731 Dept: FDS Default Group FDS fireside Fireside Group MSA JC400P 2022-01-22 2024-11-19 2042-01-23 2042-01-23
118 862798050522719 Mbuvi Kioko - KCZ 199P KCZ 199P automobile KCZ 199P Pick-Up Mbuvi Kioko 0768218655 Dept: OSP Default Group OSP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
119 862798050524087 Felix Muema - KCZ 223P KCZ 223P automobile KCZ 223P Pick-Up Felix Muema 0113973875 Dept: OSP Default Group OSP fireside Fireside Group MSA JC400P 2022-01-16 2024-12-30 2042-01-17 2042-01-17
120 862798050522891 Lawrence Kijogi - KCY 080X KCY 080X automobile KCY 080X Pick-Up Lawrence Kijogi 0113287191 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
121 862798050524392 Ndegwa Dancun - KCG 669W KCG 669W automobile KCG 669W Probox Ndegwa Dancun 0113799173 Dept: OSP Default Group OSP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
122 862798050521752 Simon Munda - KCZ 154S KCZ 154S automobile KCZ 154S Probox Simon Munda 0113805921 Dept: ISP Default Group ISP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
123 862798050524012 Moses Wambua - KCZ 751V KCZ 751V automobile KCZ 751V Probox Moses Wambua 0113313797 Dept: ISP Default Group ISP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
124 862798050523204 Amani Kazungu - KCY 084X KCY 084X automobile KCY 084X Probox Amani Kazungu 0707892547 Dept: ISP Default Group ISP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
125 862798050523949 Joseph Kabandi - KCY 076X KCY 076X automobile KCY 076X Probox Joseph Kabandi 0113288492 Dept: ISP Default Group ISP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-16 2042-01-17 2042-01-17
126 862798050525613 Kennedy Chege - KCQ 618K KCQ 618K automobile KCQ 618K Probox Kennedy Chege 0729994247 Dept: OSP Default Group OSP fireside Fireside Group MSA JC400P 2022-01-16 2022-12-19 2042-01-17 2042-01-17
127 862798050525753 Noel Merengeni - KCY 838X KCY 838X automobile KCY 838X Probox Noel Merengeni Dept: FDS Default Group FDS fireside Fireside Group MSA JC400P 2022-01-15 2023-08-23 2042-01-16 2042-01-16
128 359857082925330 Noel Merengeni - KCY 838X KCY 838X automobile KCY 838X Probox Noel Merengeni 0794873610 Dept: FDS Default Group FDS fireside Fireside Group MSA GT06E 2020-10-26 2023-08-22 2040-10-27 2040-10-27 89254021154296723429 639021159672342
129 359857082900341 Simon Munda - KCZ 154S KCZ 154S automobile KCZ 154S Probox Simon Munda 0757236135 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-09-23 2022-12-16 2040-09-24 2040-09-24 89254021154296723312 639021159672331
130 359857082912486 Moses Wambua - KCZ 751V KCZ 751V automobile KCZ 751V Probox Moses Wambua 0792756503 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-09-23 2022-12-16 2040-09-24 2040-09-24 89254021154296723437 639021159672343
131 353549090553685 Daniel Omondi - KMFF 099Z KMFF 099Z mtc KMFF 099Z Motorbike Daniel Omondi 0112794067 0759336150 Dept: OSP-PATROL Default Group OSP-PATROL fireside Fireside Group MSA AT4 2020-09-23 2022-12-16 2040-09-24 2040-09-24 89254021334258404099 639021335840409
132 353549090567685 Daniel Kipkirui - KMFF 162Z KMFF 162Z mtc KMFF 162Z Motorbike Daniel Kipkirui 0112795498 0742532058 Dept: OSP-PATROL Default Group OSP-PATROL fireside Fireside Group MSA AT4 2020-09-23 2022-12-16 2040-09-24 2040-09-24 89254021264260388966 639021266038896
133 359857082910886 Makanda Andrew - KCZ 155P KCZ 155P automobile KCZ 155P Pick-Up Makanda Andrew 0745067338 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2020-08-23 2025-02-24 2040-08-24 2040-08-24 89254021154287138397 639021158713839
134 359857082908500 Santoes Omondi - KCZ 181P KCZ 181P automobile KCZ 181P Pick-Up Santoes Omondi 0701211974 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2020-08-23 2022-12-16 2040-08-24 2040-08-24 89254021374215155087 639021371515508
135 359857082918038 Mbuvi Kioko - KCC 199P KCC 199P automobile KCC 199P Pick-Up Mbuvi Kioko 0797318126 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2020-08-22 2022-12-16 2040-08-23 2040-08-23 89254021154287138389 639021158713838
136 359857082907973 Felix Muema - KCZ 223P KCZ 223P automobile KCZ 223P Probox Felix Muema 0757843826 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2020-08-22 2024-12-30 2040-08-23 2040-08-23 89254021154287138371 639021158713837
137 359857082042854 Elias Baya - KCZ 476E KCZ 476E automobile KCZ 476E Probox Elias Baya 0110941187 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-08-09 2022-12-16 2040-08-10 2040-08-10 89254021164224352993 639021162435299
138 359857082044280 Lawrence Kijogi - KCY 080X KCY 080X automobile KCY 080X Probox Lawrence Kijogi 0708155933 Dept: ROLLOUT Default Group ROLLOUT fireside Fireside Group MSA GT06E 2020-07-13 2022-12-16 2040-07-13 2040-07-13 89254029851005131222 639029850513122
139 359857082037185 Amani Kazungu - KCY 084X KCY 084X automobile KCY 084X Probox Amani Kazungu 0757338522 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-07-13 2022-12-16 2040-07-14 2040-07-14 89254021154287000597 639021158700059
140 359857082046145 Joseph Kabandi - KCY 076X KCY 076X automobile KCY 076X Probox Joseph Kabandi 0110850007 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-07-13 2022-12-16 2040-07-14 2040-07-14 89254021164223447158 639021162344715
141 359857082040981 Amani Sulubu - KCY 090X KCY 090X automobile KCY 090X Probox Amani Sulubu 0793375853 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2020-07-13 2022-12-16 2040-07-14 2040-07-14 89254021064168004164 639021066800416
142 359857082038977 Wilfred Kinyanjui - KCU 729C KCU 729C truck KCU 729C Crane Wilfred Kinyanjui 0110094469 Dept: GENERAL Default Group GENERAL fireside Fireside Group MSA GT06E 2020-04-05 2022-12-16 2040-04-06 2040-04-06 89254021164215938057 639021161593805
143 359857081886467 Gideon Kiprono - KCQ 215F KCQ 215F automobile KCQ 215F Probox Gideon Kiprono 0746763076 Dept: ISP Default Group ISP fireside Fireside Group MSA GT06E 2019-06-30 2022-12-16 2039-07-01 2039-07-01 89254021084186499865 639021088649986
144 359857081886905 Kennedy Chege - KCQ 618K KCQ 618K automobile KCQ 618K Probox Kennedy Chege 0746763132 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2019-06-30 2022-12-16 2039-07-01 2039-07-01 89254021084186499923 639021088649992
145 359857081887192 Ndegwa Dancun - KCG 669W KCG 669W automobile KCG 669W Probox Ndegwa Dancun 0746760191 Dept: OSP Default Group OSP fireside Fireside Group MSA GT06E 2019-06-15 2022-12-16 2039-06-16 2039-06-16 89254021084186499501 639021088649950

View file

@ -59,31 +59,6 @@ services:
timeout: 5s timeout: 5s
retries: 3 retries: 3
dashboard_api:
# Stable read-API for the Live Position + Fleet Trips map dashboards.
# Replaces the n8n webhooks (n8n was only a thin HTTP->SQL proxy).
# Calls reporting.fn_live_positions / fn_vehicle_track / fn_trips_for_map.
build:
context: .
dockerfile: Dockerfile
command: sh -c "uvicorn dashboard_api_rev:app --host 0.0.0.0 --port 8890 --workers 2"
restart: always
depends_on:
timescale_db:
condition: service_healthy
env_file: .env
environment:
# Browser origins allowed to call this API (the dashboard domains).
- DASHBOARD_CORS_ORIGINS=${DASHBOARD_CORS_ORIGINS:-https://liveposition.rahamafresh.com,https://fleetintelligence.rahamafresh.com}
# No host port binding — set a domain (e.g. fleetapi.rahamafresh.com) in the
# Coolify UI pointing to this service on port 8890. The dashboards then point
# their N8N_BASE at that domain; paths (/webhook/...) are unchanged.
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8890/health"]
interval: 30s
timeout: 5s
retries: 3
grafana: grafana:
build: build:
context: ./grafana context: ./grafana
@ -104,42 +79,6 @@ services:
# You will set the actual URL in the Coolify UI, # You will set the actual URL in the Coolify UI,
# but the service needs to expose port 3000 internally. # but the service needs to expose port 3000 internally.
pgbouncer:
# Connection pooler in front of timescale_db.
# Runbook: docs/reference/260507_pgbouncer_deployment.md
# Internal Docker network only — no host port. SCRAM passthrough via
# auth_query against the public.user_lookup() function (migration 10).
image: edoburu/pgbouncer
restart: always
depends_on:
timescale_db:
condition: service_healthy
env_file: .env
environment:
- DB_HOST=timescale_db
- DB_PORT=5432
- DB_USER=${POSTGRES_USER}
- DB_PASSWORD=${POSTGRES_PASSWORD}
- DB_NAME=${POSTGRES_DB}
- POOL_MODE=transaction
- AUTH_TYPE=scram-sha-256
- AUTH_USER=pgbouncer
# $$1 escapes docker-compose interpolation; pgbouncer sees literal $1.
- AUTH_QUERY=SELECT uname, phash FROM public.user_lookup($$1)
- MAX_CLIENT_CONN=200
- DEFAULT_POOL_SIZE=15
- MIN_POOL_SIZE=2
- RESERVE_POOL_SIZE=5
- SERVER_RESET_QUERY=DISCARD ALL
- SERVER_IDLE_TIMEOUT=600
- ADMIN_USERS=${POSTGRES_USER}
- LISTEN_PORT=6432
healthcheck:
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -p 6432 -U ${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 3
db_backup: db_backup:
build: build:
context: ./backup context: ./backup

View file

@ -1,240 +0,0 @@
# Data Flow — Ingestion → Aggregation → Views → Functions → Consumers
**Scope:** the *live* fleet pipeline only (`tracksolid` + `reporting`). The `ops` and
`dwh_gold` schemas were **purged on 2026-06-05** (migrations 12/13) — those workshop /
dispatch / SLA / utilisation features were never implemented. They are shown below only as
a struck-out "removed" footnote for historical context. (The *separate* `tracksolid_dwh`
server at 31.97.44.246:5888 is unrelated and was not touched.)
**Verified against prod 2026-06-05** (TimescaleDB hypertable + continuous-aggregate
catalog, `pg_depend` view graph, ingestion `INSERT` targets, `dashboard_api` queries,
Grafana panel SQL). Key facts that surprised the docs:
- Only `position_history` (and the empty/planned `heartbeats`, `fuel_readings`,
`temperature_readings`) are **hypertables**. `trips` and `alarms` are **plain tables**.
- `tracksolid.v_mileage_daily_cagg` is a **real TimescaleDB continuous aggregate**, not a
plain view — and it currently has **no downstream consumer**.
- `reporting.v_trips` is a **matview**, refreshed every 5 min by the in-process
`dashboard_api` background loop (FIX-D02), pg advisory-lock `920145`.
---
## Mermaid
```mermaid
flowchart TD
API["Tracksolid / Jimi API<br/>poll + push webhooks · OAuth2"]
subgraph ING["Ingestion — ts_shared_rev.py: get_conn() · api_post() · clean*()"]
IM["ingest_movement_rev.py"]
IE["ingest_events_rev.py"]
WR["webhook_receiver_rev.py"]
end
API --> IM & IE & WR
subgraph L1["L1 · Base tables + hypertables — schema: tracksolid (single source of truth)"]
LP["live_positions<br/>current fix / IMEI"]
PH[("position_history<br/>HYPERTABLE · high-res GPS trail")]
TR["trips<br/>plain table — NOT a hypertable"]
DV["devices<br/>vehicle / driver registry"]
AL["alarms<br/>plain table"]
ILOG["ingestion_log · api_token_cache"]
EMPTY["heartbeats* · fuel_readings* · temperature_readings* (HYPERTABLES, empty)<br/>device_events · fault_codes · obd_readings · parking_events · lbs_readings · geofences (empty)"]
end
IM --> LP & PH & TR & DV
IM --> ILOG
IE --> AL
WR --> EMPTY
subgraph L2["L2 · Aggregation"]
CAGG[("v_mileage_daily_cagg<br/>CONTINUOUS AGGREGATE")]
VT[("reporting.v_trips<br/>MATVIEW · ix_v_trips_trip_id")]
RLOG["reporting.refresh_log"]
end
PH -->|Timescale cont-agg policy| CAGG
TR --> VT
DV --> VT
VT -->|"REFRESH CONCURRENTLY every 300s<br/>(dashboard_api loop, adv-lock 920145)"| RLOG
subgraph L3L["L3 · Reporting views — fed by v_trips matview"]
FILT["v_filter_vehicles · v_filter_drivers<br/>v_filter_cost_centres · v_filter_cities"]
SUMM["v_daily/weekly/monthly_summary<br/>v_*_cost_centre · v_trips_today"]
VLP["v_live_positions"]
end
VT --> FILT & SUMM
LP --> VLP
subgraph L3R["L3 · Grafana views — tracksolid.* (read base tables directly)"]
GV["v_fleet_today · v_fleet_status · v_active_dispatch_map<br/>v_currently_idle · v_alarms_daily · v_fleet_km_daily<br/>v_ingestion_health · v_vehicles_not_moved_today<br/>v_driver_aggregates_daily · v_fleet_trace · v_driver_clock_*"]
end
LP --> GV
TR --> GV
DV --> GV
AL --> GV
PH --> GV
subgraph L4["L4 · Functions — reporting.* (the only API entrypoints)"]
FLP["fn_live_positions(cost_centre, acc_status)"]
FVT["fn_vehicle_track(vehicle_number, hours)"]
FTM["fn_trips_for_map(veh[], driver, cc, city, start, end)"]
NP["normalize_plate(p) · helper"]
end
LP --> FLP
DV --> FLP
PH --> FVT
VT --> FTM
NP -.-> FTM
subgraph L5["L5 · Consumers"]
DAPI["dashboard_api_rev.py<br/>FastAPI :8890 · 2 workers"]
SPA["SPAs: liveposition.* · fleetintelligence.*<br/>(rustfs / S3 single-file maps)"]
GRAF["Grafana"]
end
FLP --> DAPI
FVT --> DAPI
FTM --> DAPI
FILT --> DAPI
DAPI -->|"HTTPS · fleetapi.rahamafresh.com"| SPA
GV --> GRAF
CAGG -.->|no consumer yet| NONE(["⚠ unconsumed — no panel / API reads it"])
subgraph PARK["REMOVED 2026-06-05 — purged via migrations 12 / 13 (never implemented)"]
GONE["ops.* (tickets · dispatch_log · service_log · odometer_readings · cost_rates · kpi_targets · vw_service_forecast)<br/>dwh_gold.* (dim_vehicles · fact_daily_fleet_metrics · refresh_daily_metrics)<br/>tracksolid.v_sla_inflight · tracksolid.v_utilisation_daily + their Grafana panels"]
end
classDef hyper fill:#e1f0ff,stroke:#3b82f6,color:#0b3d91;
classDef mat fill:#fff3cd,stroke:#d4a017,color:#664d03;
classDef cagg fill:#e7f7e7,stroke:#2e9e2e,color:#1e5e1e;
classDef parked fill:#f0f0f0,stroke:#999,stroke-dasharray:5 5,color:#555;
classDef warn fill:#fdecea,stroke:#d93025,color:#a52714;
class PH hyper;
class VT mat;
class CAGG cagg;
class PARK,GONE parked;
class NONE warn;
```
---
## ASCII
```
╔══════════════════════════════════════════════╗
║ TRACKSOLID / JIMI API ║
║ (poll + push webhooks, OAuth2) ║
╚════════════════════╤═════════════════════════╝
┌──────────────────────────┬───────────┴───────────┬────────────────────────────┐
▼ ▼ ▼ ▼
┌─────────────────┐ ┌────────────────────┐ ┌──────────────────────┐
│ ingest_movement │ │ ingest_events │ │ webhook_receiver │ (all via ts_shared_rev.py:
│ _rev.py │ │ _rev.py │ │ _rev.py │ get_conn() pool, api_post(),
└────────┬────────┘ └─────────┬──────────┘ └──────────┬───────────┘ clean*() , token cache)
│ │ │
│ writes │ writes │ writes (push)
▼ ▼ ▼
╔════════════════════════════════════════════════════════════════════════════════════════════╗
║ L1 · BASE TABLES + HYPERTABLES schema: tracksolid (single source of truth) ║
║ ║
║ live_positions ── current fix / IMEI (plain) api_token_cache (auth) ║
║ position_history ◀═══ HYPERTABLE (high-res GPS trail, partitioned by gps_time) ║
║ trips ── trip summaries (plain table — NOT a hypertable) ║
║ devices ── vehicle/driver registry (plain) ║
║ alarms ── alarm events (plain table) ║
║ ingestion_log ── API audit trail (plain) ║
║ heartbeats*, fuel_readings*, temperature_readings* ◀═ HYPERTABLES (empty / planned push) ║
║ device_events, fault_codes, obd_readings, parking_events, lbs_readings, geofences (empty) ║
╚══════╤══════════════════════════╤══════════════════════════════════╤════════════════════════╝
│ │ │
│ TimescaleDB │ matview refresh │ direct reads
│ cont-agg policy │ (in-app loop) │ (Grafana SQL)
▼ ▼ ▼
╔══════════════════╗ ╔════════════════════════════════╗ ╔══════════════════════════════════╗
║ L2 · AGGREGATION ║ ║ L2 · AGGREGATION (matview) ║ ║ L3 · GRAFANA VIEWS (tracksolid.*) ║
║ ║ ║ ║ ║ read base tables directly ║
║ v_mileage_daily ║ ║ reporting.v_trips [MATVIEW] ║ ║ ║
║ _cagg ║ ║ ◀── trips + devices ║ ║ v_fleet_today v_fleet_status ║
║ CONTINUOUS AGG ║ ║ unique ix_v_trips_trip_id ║ ║ v_active_dispatch_map ║
║ ◀═ position_ ║ ║ ║ ║ v_currently_idle v_alarms_daily ║
║ history ║ ║ REFRESH … CONCURRENTLY every ║ ║ v_fleet_km_daily v_ingestion_health║
║ (auto refresh ║ ║ VTRIPS_REFRESH_INTERVAL_S=300 ║ ║ v_vehicles_not_moved_today ║
║ policy) ║ ║ by dashboard_api bg asyncio ║ ║ v_driver_aggregates_daily ║
╚════════╤═════════╝ ║ loop, pg advisory-lock 920145 ║ ║ v_fleet_trace ║
│ ║ │ ║ ║ v_driver_clock_daily/_today/_attnd ║
│ ║ └──▶ reporting.refresh_log ║ ╚══════════════╤═════════════════════╝
│ ╚═══════════════╤════════════════╝ │
│ │ │
│ ▼ │
│ ╔════════════════════════════════════════════╗ │
│ ║ L3 · REPORTING VIEWS (← v_trips matview) ║ │
│ ║ v_filter_vehicles v_filter_drivers ║ │
│ ║ v_filter_cost_centres v_filter_cities ║ │
│ ║ v_daily/weekly/monthly_summary ║ │
│ ║ v_*_cost_centre v_trips_today ║ │
│ ║ v_live_positions (view, ← live_positions) ║ │
│ ╚════════════════════════╤═══════════════════╝ │
│ │ │
│ ╔══════════════════════════════════╧═══════════════════╗ │
│ ║ L4 · FUNCTIONS (schema reporting — API entrypoints) ║ │
│ ║ ║ │
│ ║ fn_live_positions(cost_centre, acc_status) ║ │
│ ║ ◀── live_positions + devices ║ │
│ ║ fn_vehicle_track(vehicle_number, hours) ║ │
│ ║ ◀── position_history (hypertable trail) ────────╫─────┘ (also reads L1)
│ ║ fn_trips_for_map(veh[],driver,cc,city,start,end) ║
│ ║ ◀── reporting.v_trips (matview) ║
│ ║ normalize_plate(p) ── helper used by the above ║
│ ╚════════════════════════════╤══════════════════════════╝
│ │
▼ ▼
(cagg currently ╔═══════════════════════════════════════════════╗
unconsumed — ║ L5 · CONSUMERS ║
no panel/API yet) ║ ║
║ dashboard_api_rev.py (FastAPI :8890, ×2 wkrs) ║
║ POST /webhook/fleet-dashboard → fn_trips_for_map + v_filter_*
║ GET /webhook/live-positions → fn_live_positions
║ GET /webhook/live-positions/track → fn_vehicle_track
║ │ ║
║ ▼ HTTPS (fleetapi.rahamafresh.com) ║
║ SPAs: liveposition.* · fleetintelligence.* ║
║ (rustfs/S3 single-file maps) ║
║ ║
║ Grafana ──SQL──▶ tracksolid.v_* (L3 right) ║
╚═══════════════════════════════════════════════╝
┌─ REMOVED 2026-06-05 · purged via migrations 12 / 13 (never implemented) ───────────────┐
│ ops.* : tickets, dispatch_log, service_log, odometer_readings, │
│ cost_rates, kpi_targets, vw_service_forecast │
│ dwh_gold.* : dim_vehicles, fact_daily_fleet_metrics, refresh_daily_metrics() │
│ tracksolid : v_sla_inflight, v_utilisation_daily (+ their Grafana panels removed) │
│ → Schemas dropped from prod. The separate tracksolid_dwh server is unrelated/untouched.│
└────────────────────────────────────────────────────────────────────────────────────────┘
```
---
## How to read it
- **L1** is where ingestion lands. Only `position_history` (and three empty/planned
hypertables) are TimescaleDB hypertables; `trips`/`alarms` are ordinary tables.
- **Two aggregation mechanisms** run in parallel: the TimescaleDB **continuous aggregate**
`v_mileage_daily_cagg` (refreshed by a Timescale policy off `position_history`), and the
**`reporting.v_trips` matview** (refreshed every 5 min by the in-process `dashboard_api`
loop — the FIX-D02 self-refresher that replaced the dead n8n job).
- **L4 functions are the only thing the API calls.** SPAs never touch tables directly:
SPA → `dashboard_api``fn_*` → (matview / tables).
- **Grafana** takes the right-hand path, reading the `tracksolid.v_*` analytics views
straight off L1.
## Caveats / housekeeping notes
1. **`v_mileage_daily_cagg` has no consumer** — nothing in the API or Grafana reads it. It
is a live continuous aggregate maintaining itself for nobody. Candidate for removal or
wiring into a panel.
2. **`ops` and `dwh_gold` were purged** (2026-06-05, migrations 12/13) along with
`v_utilisation_daily`, `v_sla_inflight`, and their Grafana panels — the features were
never implemented.
3. See the companion housekeeping audit (2026-06-05) for the full unused-object list; the
only clean ad-hoc drop is `public.trips_viz_v1`.

View file

@ -1,252 +0,0 @@
# DWH Pipeline — Operations Runbook
**Pipeline:** n8n extract + load into `tracksolid_dwh` bronze schema
**Design spec:** `docs/superpowers/specs/2026-04-24-n8n-dwh-bronze-pipeline-design.md`
**Implementation plan:** `docs/superpowers/plans/2026-04-24-n8n-dwh-bronze-pipeline.md`
---
## 1. What This Pipeline Does
Every ~3 hours during active hours (7 runs/day, 05:0023:00 EAT), n8n extracts 8 tables from the production `tracksolid_db` (Coolify internal network), writes each as a timestamped CSV to rustfs, then loads each CSV into the `bronze` schema on `tracksolid_dwh` (31.97.44.246:5888). Rustfs CSVs are moved to `dwh/processed/` after a successful load — never deleted.
Two n8n workflows:
- **`dwh_extract`** — cron-triggered, iterates tables in sequence, writes CSVs, calls `dwh_load_bronze` per table.
- **`dwh_load_bronze`** — triggered per-table by `dwh_extract`, loads one CSV inside a single transaction (insert → update watermark → update run log → move CSV).
---
## 2. Key Locations
| What | Where |
|---|---|
| Source DB | `tracksolid_db` on Coolify (internal Docker network, `timescale_db:5432`) |
| Target DB | `tracksolid_dwh` at `31.97.44.246:5888` |
| Rustfs bucket | `fleet-db` (same bucket used by pg_dump backups) |
| Active CSVs | `s3://fleet-db/dwh/exports/{table}/{YYYYMMDD_HHMM}_EAT.csv` |
| Processed CSVs | `s3://fleet-db/dwh/processed/{table}/{YYYYMMDD_HHMM}_EAT.csv` |
| Control schema | `dwh_control` in `tracksolid_dwh` |
| Migrations | `dwh/26*.sql` applied in numeric order |
---
## 3. First-Time Setup
Apply migrations to `tracksolid_dwh` in numeric order, as a superuser (not `dwh_owner`):
```bash
PSQL="psql 'postgres://postgres:***@31.97.44.246:5888/tracksolid_dwh?sslmode=require'"
$PSQL -f dwh/260423_dwh_ddl_v1.sql # Bronze DDL, roles, schemas
$PSQL -f dwh/261001_dwh_control.sql # Watermarks + run log
$PSQL -f dwh/261002_bronze_constraints_audit.sql # Assertion: ON CONFLICT keys exist
$PSQL -f dwh/261003_dwh_roles.sql # Assertion: roles + grants present
$PSQL -f dwh/261004_dwh_observability_views.sql # Freshness/failure views
```
Each migration is idempotent. Audit files (261002, 261003) raise an exception with a bullet list of what is missing if the contract is broken — re-apply the relevant predecessor file and try again.
### Rustfs prefixes
```bash
aws --endpoint ${RUSTFS_ENDPOINT} s3api put-object \
--bucket fleet-db --key dwh/exports/
aws --endpoint ${RUSTFS_ENDPOINT} s3api put-object \
--bucket fleet-db --key dwh/processed/
```
### n8n credentials
Three credentials, all configured in the n8n UI before importing workflows:
| Credential | Target | User | Notes |
|---|---|---|---|
| `tracksolid_source` | Coolify internal → `tracksolid_db` | `grafana_ro` | Read-only; no `sslmode` needed on internal network |
| `tracksolid_dwh_target` | `31.97.44.246:5888``tracksolid_dwh` | `dwh_owner` | **Must set `sslmode=require`** — public IP |
| `rustfs_s3` | `${RUSTFS_ENDPOINT}` | `${RUSTFS_ACCESS_KEY}` | Same creds as pg_dump backup sidecar |
Test each credential via the n8n "Test connection" button before enabling the cron schedule.
---
## 4. Schedule
n8n Schedule node, Africa/Nairobi TZ: `0 5,8,11,14,17,20,23 * * *`
- 7 runs/day at 05:00, 08:00, 11:00, 14:00, 17:00, 20:00, 23:00 EAT
- Overnight gap (23:00 → 05:00 = 6h) by design — device traffic minimal
- First-of-day run carries the overnight backlog (watermark picks up where 23:00 left off)
---
## 5. What Each Table Does on Every Run
### Snapshot tables (TRUNCATE + full reload)
`bronze.devices`, `bronze.live_positions` — small state tables, "current state" semantics. Full replace every run.
### Incremental tables (watermark + append-with-dedup)
| Bronze table | Source watermark column | ON CONFLICT target |
|---|---|---|
| `position_history` | `recorded_at` (DB insertion time) | `(imei, gps_time)` |
| `trips` | `updated_at` | `id` |
| `alarms` | `updated_at` | `id` |
| `parking_events` | `updated_at` | `id` |
| `device_events` | `created_at` | `id` |
| `ingestion_log` | `run_at` | `id` |
Watermark bounds are closed upper: `WHERE <col> > last_extracted_at AND <col> <= :run_started_at`.
### Schema drift to handle in extract SQL
- **`trips.distance_m``bronze.trips.distance_km`**: source stores metres, bronze expects km. Extract SQL: `SELECT ..., distance_m/1000.0 AS distance_km, ...`. Cross-reference: FIX-M16 in `CLAUDE.md`.
### PostGIS geometry round-trip
All six geometry columns (`live_positions`, `position_history`, `trips.start_geom`, `trips.end_geom`, `parking_events`, `alarms`) use EWKT serialisation:
```sql
-- Extract
SELECT ..., CASE WHEN geom IS NULL THEN NULL ELSE ST_AsEWKT(geom) END AS geom_ewkt FROM ...;
-- Load
INSERT INTO bronze... (..., geom) VALUES (..., ST_GeomFromEWKT(:geom_ewkt));
```
SRID 4326 is preserved inline; no separate SRID step required.
---
## 6. Verifying a Healthy Run
### Immediate sanity checks (after any scheduled run)
```sql
-- Any failures in the last hour?
SELECT * FROM dwh_control.v_recent_failures WHERE run_started_at > NOW() - INTERVAL '1 hour';
-- All tables loaded in last 4h?
SELECT * FROM dwh_control.v_table_freshness WHERE lag > INTERVAL '4 hours';
-- Watermarks advancing?
SELECT * FROM dwh_control.v_watermark_lag ORDER BY extract_lag DESC;
```
### Row-count parity (spot check weekly)
```sql
-- Source
SELECT COUNT(*) FROM tracksolid.position_history;
-- Target
SELECT COUNT(*) FROM bronze.position_history;
```
Numbers should match ± rows inserted between the two queries. Persistent gap > 1% → investigate CSV parse errors or a dropped batch.
### Geometry round-trip
```sql
SELECT ST_AsText(geom) FROM bronze.position_history WHERE geom IS NOT NULL LIMIT 5;
-- Should return valid POINT(lng lat), not NULL or garbage.
```
---
## 7. Troubleshooting
### "A table is stale (`v_table_freshness` shows lag > 4h)"
1. Check `v_recent_failures` for that table. If a row exists, read `error_message`.
2. If `status='loading'` in `extract_runs` for that table, a load is in progress — wait for the next cron tick. If it stays `loading` across two ticks, the n8n executor crashed mid-transaction; the DB rolled back, and the next run will retry naturally.
3. If no failure row and no in-progress row, the extract workflow never fired — check n8n execution logs for the cron trigger.
### "A CSV is stuck in `dwh/exports/`"
The load failed after upload. The next scheduled run will re-process it (the watermark did not advance, so the extract SQL returns the same window). Safe to leave. If multiple days of CSVs pile up, the load workflow has a persistent bug — open n8n execution logs for the specific `run_id` in `extract_runs`.
### "Row counts diverge more than ~1%"
Usually one of:
- A retry window overlapped the PK range and some rows lost the race with a concurrent source-side write. Re-trigger the extract for that window manually (see §8).
- CSV parse error silently dropped a row. Check `extract_runs.rows_extracted` vs. `rows_loaded` — if they differ, the loader found malformed CSV.
### "Geometry loaded as NULL"
EWKT serialisation broke on the extract side. Verify the source query has the `CASE WHEN geom IS NULL` guard — without it, `ST_AsEWKT(NULL)` returns `NULL` correctly but an empty geometry returns `'GEOMETRYCOLLECTION EMPTY'` which `ST_GeomFromEWKT` rejects.
### "`bronze.trips.distance_km` values are 1000× too large"
The extract query is missing `/1000.0` on the source `distance_m` column. See §5 "Schema drift".
---
## 8. Manual Re-Run
### Re-run a single table for the current window
1. Open n8n, go to `dwh_extract` workflow.
2. Locate the branch for that table.
3. Click **Execute Workflow** → selects that table only.
4. Confirm a new row appears in `dwh_control.extract_runs` with `status='loaded'`.
### Back-fill a historical window
The extract workflow respects the watermark; to re-extract a window, rewind the watermark:
```sql
-- Rewind position_history to 24h ago
UPDATE dwh_control.extract_watermarks
SET last_extracted_at = NOW() - INTERVAL '24 hours'
WHERE table_name = 'position_history';
```
Next scheduled run will re-extract the gap. Loads are idempotent (`ON CONFLICT DO NOTHING` on the PK), so duplicate rows are filtered at the bronze boundary.
### Full reseed (nuclear option)
```sql
-- Restart position_history from the beginning
UPDATE dwh_control.extract_watermarks
SET last_extracted_at = '2026-01-01T00:00:00Z'
WHERE table_name = 'position_history';
```
The first post-reseed run will produce one very large CSV (~all history). The rustfs `exports/` prefix will briefly hold a multi-GB object. Expected; it moves to `processed/` on success.
---
## 9. Credential Rotation
`260423_dwh_ddl_v1.sql` commits role passwords in plaintext — a pre-existing flaw to be cleaned up separately.
To rotate:
```sql
-- As superuser on tracksolid_dwh:
ALTER ROLE dwh_owner PASSWORD '<new secret>';
ALTER ROLE grafana_ro PASSWORD '<new secret>';
```
Then update the matching n8n credential and Grafana datasource. Never commit the new password — store in `.env` if needed for scripts, or keep exclusively inside n8n/Grafana credential stores.
---
## 10. Known Quirks
| Quirk | Source | Handling |
|---|---|---|
| `trips.distance_m``bronze.trips.distance_km` | Schema drift between source and bronze | Divide in extract SQL (§5) |
| Hypertable row counts read 0 in `pg_stat_user_tables` | TimescaleDB quirk | Always `SELECT COUNT(*)` directly |
| `parking_events` can be empty for days | Endpoint returns empty; not a failure | Zero rows loaded is a valid run outcome |
| First run of each day larger | Overnight backlog | Expected; plan watermark design |
| `last_extracted_at` default `2026-01-01` | Seed value from 261001 | First run on a new table back-fills all history |
---
## 11. Out of Scope (follow-up)
- Silver/gold transformations — `silver` and `gold` schemas exist but contain no views.
- Grafana dashboard panels — these views are the data source; panels TBD.
- OBD / fault codes / fuel / temperature / LBS / heartbeats — webhooks not yet registered; add a watermark row + extract branch when they start reporting.
- Bronze schema evolution tooling — additive changes via numbered migrations is fine for one pipeline; revisit if scope grows.

View file

@ -1,50 +0,0 @@
# OSM POI Export → FleetNow map layer
How we turn an OpenStreetMap extract into a toggleable **FleetNow overlay layer**
(e.g. the 232 Shell fuel stations). Reproducible end-to-end.
## 1. Get a Kenya extract
Download a `.osm.pbf` (Geofabrik / BBBike), e.g. `kenya-260605.osm.pbf`.
> **Do not commit the `.pbf`** — it's ~331 MB and is gitignored (`*.osm.pbf`).
> It's fully reproducible from the download.
## 2. Export the POIs
No system tooling required — `pyosmium`'s prebuilt wheel is fetched by `uv`:
```bash
uv run --no-project --with osmium python scripts/export_osm_pois.py \
kenya-260605.osm.pbf --amenity fuel --brand Shell \
--out-geojson shell_stations.geojson --out-csv shell_stations.csv
```
- Gas stations are OSM **`amenity=fuel`**. Brand is the **`brand`** tag — but only
~36% of Kenyan stations carry it (≈92% have a `name`), so when `--brand` is given
and a feature has no `brand` tag, the script falls back to matching `name`/`operator`.
- Omit `--brand` to export **every** station of that amenity.
- Nodes use their own coordinate; ways/areas use their node **centroid**.
**Reference counts** (extract `kenya-260605`, captured 2026-06-08):
| Metric | Value |
|---|---|
| Total fuel stations (`amenity=fuel`) | 1,794 (1,582 nodes + 212 areas) |
| With a `brand` tag | 659 (36%) · with a `name` | 1,652 (92%) |
| **Shell** | **232** (209 `brand=Shell` + 23 by name) |
| Other top brands | Total 154 · Rubis 147 · TotalEnergies 50 · Kobil 10 |
## 3. Add it to FleetNow as a layer
Copy the GeoJSON into the FleetNow repo's `layers/` directory and register it —
full details in the **fleetnow** repo `README.md`*"Map overlay layers"*:
```bash
cp shell_stations.geojson ../fleetnow/layers/
# then add one entry to the OVERLAYS array in fleetnow/index.html, commit + push.
```
FleetNow keeps its own served copy under `fleetnow/layers/`; the artifact here
(`shell_stations.geojson` / `.csv`) is the export of record. Re-running step 2 on a
newer extract and re-copying refreshes the layer.

File diff suppressed because one or more lines are too long

View file

@ -1,74 +0,0 @@
# FleetNow — One Fleet, One Screen
### Bringing live tracking and trip history together into a single intelligence platform
*Audience: Senior Directors · Prepared 2026-06-08*
---
## The big idea
The legacy setup answered two questions in two different places: *"Where is the fleet right now?"* on one dashboard, and *"Where has it been?"* on another. **FleetNow merges them into a single live map** — so the moment you see a vehicle, its full history is one click away. No switching tools, no reconciling two screens, no losing the thread.
> **"Where is it now"** and **"where has it been"** — finally answered in the same place, at the same time.
## Why one platform beats two
| | Legacy: two separate dashboards | **FleetNow: unified platform** |
|---|---|---|
| **Workflow** | Toggle between live + history tools, rebuild context each time | One screen, one flow — live and history side by side |
| **Decisions** | Piece the story together across tabs | Dispatch, investigate, and review in a single view |
| **Filters** | Set them twice, hope they match | One filter (city, cost centre, vehicle) applies everywhere |
| **Data trust** | Two sources that can quietly disagree | One source of truth — live and historical always agree |
| **Onboarding** | Learn two tools | Learn one — faster for new staff |
| **Upkeep** | Two apps to maintain | One platform, lower cost and risk |
**The headline:** merging live + historical isn't just tidier — it's *faster decisions, fewer errors, and a single trusted picture of the fleet.*
## What's new and powerful
**🗺️ A living operations map**
- Real-time vehicle positions refreshed continuously, with movement, idle, and offline states colour-coded at a glance.
- Click any vehicle to drop straight into its trip history — routes, stops, distances, timing.
**🎨 Instant visual read of the fleet**
- **Colour-coordinated by department** (ISP, OSP, FDS…) — spot how each team is deployed across the city in a single glance, with a one-tap colour key.
- **Distinct icons for specialist assets** — cranes, motorbikes, and pick-ups stand out from the field-service fleet, so the vehicles that close customer tickets are never confused with heavy/infrastructure units.
**🎯 Built for *your* operation, not a generic tracker**
- The map shows the **operational fleet only** — personal, management, and out-of-region vehicles are filtered out, so leaders see what actually matters to service delivery.
- Tracker + dashcam are intelligently paired into **one vehicle**, so counts and lists reflect reality (not double-counted devices).
**📊 One source of truth, automatically current**
- Vehicle types, drivers, and assignments flow straight from the source system — the platform stays accurate without manual upkeep.
- The same trusted data powers the live map, trip history, and management analytics.
## What this means for the business
- **Faster, better decisions** — dispatch and respond from a single, current view.
- **Real accountability** — every trip tied to a vehicle, driver, and department.
- **Clarity for leadership** — see fleet activity by team and city at a glance.
- **Lower cost & risk** — one platform to run and train on, not several.
- **A foundation to build on** — utilisation, SLA, and cost insights plug into the same trusted base.
## Where we're headed
FleetNow is a living platform. On the near-term roadmap: always-on visibility of specialist assets, richer per-department analytics, and deeper KPI dashboards for service performance — all on the same single, trusted foundation.
> **From two disconnected dashboards to one intelligent platform — that's the leap.**
---
## Demo flow & talking points
**The one-line message:** *"We merged live tracking and trip history into one intelligent platform — one screen, one source of truth, purpose-built for our field-service fleet."*
**Live demo (≈34 minutes):**
1. **Open the live map** — "This is the whole operational fleet, right now, across our cities."
2. **Point out the colours** — open the **Key**: "Each department has its own colour — here's ISP, OSP, FDS at a glance."
3. **Read the states** — "Bright ones are moving now, faded are recently stopped, grey are offline — instant situational awareness."
4. **Spot a specialist** — "These icons are our cranes and motorbikes — clearly separate from the ticket-closing fleet."
5. **Click a vehicle → its trips** — "And here's the power of merging: from a live pin, straight into where this vehicle has been today, same screen."
6. **Apply a filter** — "Filter by department or city once, and it holds across both live and history."
7. **Land the close** — "One screen. One trusted source. No more switching tools."
**Three points to repeat:**
- **One platform, not two** — faster decisions, less friction.
- **One source of truth** — live and historical can't disagree.
- **Built for us** — segmented fleet, department colours, real accountability.

File diff suppressed because it is too large Load diff

View file

@ -1,69 +0,0 @@
# FleetNow — Your Team, Live and in Full
### One screen to see your crews, dispatch in the moment, and review after
*Audience: Heads of Department · Prepared 2026-06-08*
---
## The big idea
You shouldn't have to jump between a "where are they now" screen and a separate "where did they go" screen to run your day. **FleetNow puts both on one map** — see your vehicles live, then click straight into any vehicle's trips without losing your place. Act in the moment; review when you need to.
> See your team **right now**, and everywhere they've **been today** — without ever leaving the map.
## Why one screen beats two (for your day)
| | Legacy: two dashboards | **FleetNow: one screen** |
|---|---|---|
| **Running your shift** | Flip between live + history tools | Everything in one place — dispatch and check history together |
| **Finding your team** | Hunt through a full fleet list | Your department has its **own colour** — spot your crews instantly |
| **Settling a question** | Cross-check two tools (and a spreadsheet) | Click the vehicle → see its trips on the spot |
| **Trusting the numbers** | Two sources that can disagree | One source — live and history always match |
## What's new — and how it helps your team
**🎨 Your department, in its own colour**
Every team has a dedicated colour on the map (ISP, OSP, FDS…). At a glance you can see *your* crews, where they are, and how they're spread across the city — with a one-tap colour key so nobody has to memorise anything.
**🟢 Read the situation instantly**
Colour intensity tells the story: **bright = moving now**, softer = stopped recently, grey = offline 24h+. You can see who's active, who's idle, and who's gone quiet — without clicking a thing.
**🎯 Know your ticket-closers from your heavy units**
Cranes, motorbikes, and pick-ups now carry their **own icons**, clearly set apart from the field-service vehicles that close customer tickets — so the fleet that drives your SLAs is never confused with specialist assets.
**👤 Every trip tied to a driver**
Live position *and* trip history both link to the vehicle, plate, and driver — so performance conversations, job verification, and dispute resolution are backed by data, not memory.
**🧹 A clean, honest view**
Personal, management, and out-of-region vehicles are filtered out, and each tracker+dashcam pair shows as **one vehicle** — so your map reflects the real operational fleet, nothing more.
## What this means for your department
- **Dispatch faster** — find the nearest available crew in seconds.
- **Chase the gaps** — spot idle or silent vehicles before they cost you a missed SLA.
- **Back your team with facts** — utilisation, routes, and timing on demand.
- **Less admin** — one tool, no reconciling screens or spreadsheets.
- **Make your numbers look real** — accurate counts, clear accountability.
## Where it's headed
More to come on the same trusted foundation: always-on visibility for specialist assets, per-department performance dashboards, and SLA/utilisation insights — built around how your teams actually work.
> **From two disconnected dashboards to one screen that runs your day.**
---
## Demo flow & talking points
**The one-line message:** *"We merged live tracking and trip history into one intelligent platform — one screen, one source of truth, purpose-built for our field-service fleet."*
**Live demo (≈34 minutes):**
1. **Open the live map** — "This is the whole operational fleet, right now, across our cities."
2. **Point out the colours** — open the **Key**: "Each department has its own colour — here's ISP, OSP, FDS at a glance."
3. **Read the states** — "Bright ones are moving now, faded are recently stopped, grey are offline — instant situational awareness."
4. **Spot a specialist** — "These icons are our cranes and motorbikes — clearly separate from the ticket-closing fleet."
5. **Click a vehicle → its trips** — "And here's the power of merging: from a live pin, straight into where this vehicle has been today, same screen."
6. **Apply a filter** — "Filter by department or city once, and it holds across both live and history."
7. **Land the close** — "One screen. One trusted source. No more switching tools."
**Three points to repeat:**
- **One platform, not two** — faster decisions, less friction.
- **One source of truth** — live and historical can't disagree.
- **Built for us** — segmented fleet, department colours, real accountability.

File diff suppressed because it is too large Load diff

View file

@ -1,385 +0,0 @@
# DWH Execution Manual
> **Purpose:** A reusable playbook for building an `extract → blob → load` data warehouse bronze layer using n8n (or any equivalent orchestrator) + object storage + PostgreSQL/PostGIS. Generalised from the Fireside Tracksolid DWH pipeline (2026-04-24). Apply this pattern to future data projects to skip re-deriving the same decisions.
>
> **Reference implementation:** `dwh/26100{1..4}.sql` + `docs/DWH_PIPELINE.md` + the two `n8n-workflows/dwh_*.json` files. Treat those as the copy-paste template for the next project.
---
## 1. When to Use This Pattern
**Use it when all of these are true:**
- You need an analytical replica of a production OLTP DB without letting analytical load hit the OLTP.
- Source and target are separate PostgreSQL instances (possibly separate networks).
- Data volumes are moderate: millions of rows per day, not billions.
- You already have an orchestrator (n8n, Airflow, Prefect) and object storage (rustfs, S3, MinIO) in the stack.
- Latency tolerance is hours, not minutes.
**Don't use it when:**
- Sub-minute latency is required → use logical replication or CDC (Debezium, pg_logical, AWS DMS).
- Volumes exceed ~100 GB/day → step up to Spark/Flink + columnar store (Iceberg, Delta).
- Source and target are the same DB → just use materialized views or scheduled SQL.
- You need exactly-once streaming semantics → this pattern is at-least-once + idempotent load.
---
## 2. The Core Pattern
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Source DB │──(a)──▶ Orchestr. │──(b)──▶ Object Store │──(c)──▶ Target DB │
│ (OLTP) │ │ (extract) │ │ (CSVs) │ │ (bronze) │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ ▲
└──────────────(d)─────────────────────────────┘
(load workflow, per CSV)
(a) Watermarked SELECT, closed upper bound
(b) Atomic CSV upload with timestamped path
(c) CSV stays until load confirms success
(d) Load = BEGIN → INSERT ON CONFLICT → UPDATE watermark → UPDATE run log → COMMIT → move CSV
```
**Why three stages and not two:**
- **Audit trail** — every extracted CSV is a point-in-time snapshot you can replay.
- **Decoupling** — target DB downtime doesn't lose data; the CSV waits.
- **Observability** — blob listings are a second source of truth independent of the DB.
---
## 3. Pre-flight Checklist
Before writing any SQL or workflow JSON, confirm in writing:
- [ ] Source DB reachable from orchestrator (internal network preferred, VPN/public IP with `sslmode=require` otherwise).
- [ ] Target DB reachable; you hold a superuser credential for one-time DDL.
- [ ] Object storage bucket exists; credentials are configured in the orchestrator.
- [ ] For each source table to extract, you have identified:
- A **DB-insertion timestamp column** (not device/user-reported time), or "it's a snapshot table".
- A **natural unique key** that already has a `PRIMARY KEY` or `UNIQUE` constraint on source (for the `ON CONFLICT` target on bronze).
- Any **unit/column drift** between source and target (e.g., `distance_m` vs. `distance_km`).
- [ ] Acceptable end-to-end latency (to calibrate cron cadence).
- [ ] Security baseline: who writes bronze, who reads it, SSL requirement, password rotation cadence.
If any row is unchecked, pause and resolve it. Skipping this step is the #1 cause of pipelines that "worked in test but lose data in prod."
---
## 4. Phase-by-Phase Execution
Execute in order. Phases are independent of each other within their phase, but phases have strict dependencies.
### Phase A — Target DB preparation
Apply three types of migrations, in numeric order:
1. **Bronze DDL** — one table per source table. Use `IF NOT EXISTS`; make it idempotent.
2. **Control schema**`dwh_control.extract_watermarks` + `dwh_control.extract_runs`.
3. **Assertion migrations** — verify roles exist, verify every `ON CONFLICT` target is backed by a PK/UNIQUE (fail loudly if not).
Template files: `dwh/260423_dwh_ddl_v1.sql`, `dwh/261001_dwh_control.sql`, `dwh/261002_bronze_constraints_audit.sql`, `dwh/261003_dwh_roles.sql`.
**Role model:**
- `<proj>_owner` — owns schemas, writes bronze + control tables.
- `<proj>_ro` (or `grafana_ro`) — reads everything, writes nothing.
- Never use `postgres` or another superuser from the orchestrator.
**Watermark seed:** set `last_extracted_at` to a date before any real data (`'2000-01-01T00:00:00Z'` is safe) so the first run back-fills all history in a single CSV per table.
### Phase B — Object storage
Create two prefixes per table:
```
s3://<bucket>/<project>/exports/{table}/ # active CSVs, in-flight
s3://<bucket>/<project>/processed/{table}/ # loaded CSVs, never deleted (audit)
```
Naming convention: `{YYYYMMDD_HHMM}_{TZ}.csv` (e.g., `20260424_1400_EAT.csv`). Timezone in the filename because "08:00" means nothing a year from now without it.
Retention: match whatever backup retention is already in the stack (e.g., 30 days). `processed/` should outlive `exports/`.
### Phase C — Orchestrator credentials
Three credentials:
| Credential | Role | Purpose |
|---|---|---|
| `<proj>_source` | Read-only role on source DB | Extract queries |
| `<proj>_dwh_target` | `<proj>_owner` on target DB | Bronze writes + control updates |
| `<proj>_s3` | IAM user with `s3:PutObject`, `s3:GetObject`, `s3:ListBucket`, `s3:DeleteObject` on the prefix | CSV upload/download/move |
**Always** `sslmode=require` on any public-IP DB connection. Test each credential with the orchestrator's "Test connection" button before proceeding.
### Phase D — Load workflow (build this BEFORE the extract workflow)
Building load first lets you iterate with hand-crafted CSVs in blob storage before wiring up extract. Much faster feedback loop.
Load workflow input (parameters):
```json
{
"table": "position_history",
"csv_path": "s3://bucket/project/exports/position_history/20260424_1400_EAT.csv",
"run_id": 12345,
"run_started_at": "2026-04-24T11:00:00Z"
}
```
Load workflow steps:
1. Download CSV from blob storage.
2. Parse CSV into rows.
3. **Open transaction.**
4. `INSERT INTO bronze.<table> (...) VALUES (...) ON CONFLICT (<natural_key>) DO NOTHING;`
5. `UPDATE dwh_control.extract_watermarks SET last_extracted_at = :run_started_at, last_loaded_at = NOW(), rows_loaded_last_run = <count> WHERE table_name = :table;`
6. `UPDATE dwh_control.extract_runs SET status = 'loaded', run_finished_at = NOW(), rows_loaded = <count> WHERE run_id = :run_id;`
7. **Commit.**
8. Move CSV from `exports/` to `processed/` (copy-then-delete; never delete before copy confirms).
**Non-negotiable invariants:**
- Steps 37 are one transaction. If any fails, all rollback.
- Step 8 only runs after commit. If step 8 fails, the next run will re-load the CSV (idempotent via ON CONFLICT) — not a data loss event.
### Phase E — Extract workflow
Extract workflow steps, per table:
1. Read current watermark: `SELECT last_extracted_at FROM dwh_control.extract_watermarks WHERE table_name = :table;`
2. Capture `run_started_at = NOW()` (in the target DB's clock, not the orchestrator's — reduces clock-skew bugs).
3. `INSERT INTO dwh_control.extract_runs (table_name, run_started_at, status) VALUES (:table, :run_started_at, 'extracting') RETURNING run_id;`
4. Query source with closed upper bound:
```sql
SELECT <cols>
FROM <source_schema>.<table>
WHERE <watermark_col> > :last_extracted_at
AND <watermark_col> <= :run_started_at
ORDER BY <watermark_col>;
```
5. Render rows as CSV. For geometry columns: `CASE WHEN geom IS NULL THEN NULL ELSE ST_AsEWKT(geom) END`.
6. Upload CSV to `s3://bucket/project/exports/{table}/{YYYYMMDD_HHMM}_{TZ}.csv`.
7. `UPDATE dwh_control.extract_runs SET status = 'uploaded', rows_extracted = <count>, csv_path = :path WHERE run_id = :run_id;`
8. Call load workflow with `{table, csv_path, run_id, run_started_at}`.
### Phase F — Schedule + observability
**Cron cadence:** start with 68 runs/day during active hours. Fold the overnight gap where traffic is low. Example: `0 5,8,11,14,17,20,23 * * *` TZ `Africa/Nairobi`.
**Three observability views** (readable by the RO role):
- `v_table_freshness` — per-table lag from last successful load. Drives the freshness alert.
- `v_recent_failures` — failed runs in last 24h. Zero rows = healthy.
- `v_watermark_lag` — extract vs. load lag per table. Distinguishes "nothing to extract" from "stuck".
Template file: `dwh/261004_dwh_observability_views.sql`.
**Grafana panels** (add at minimum):
1. Freshness panel — red if any row in `v_table_freshness` has `lag > 4h`.
2. Failures panel — red if `v_recent_failures` has any row.
3. Row counts panel — daily bar chart from `extract_runs`.
---
## 5. Design Principles (Do Not Skip)
### 5.1 Watermark on DB insertion time, not source-reported time
The watermark column must be "when the target DB got the row", not "when the device/user said it happened". Device clocks skew, webhooks arrive late, and batch imports backdate records. A source-reported watermark will silently drop rows that arrive out of order. Use `recorded_at`, `created_at`, `updated_at` (with `DEFAULT NOW()`), or `ingested_at` — never `gps_time` / `event_time` / `timestamp`.
### 5.2 Closed upper bound
Extract uses `> last_extracted_at AND <= run_started_at`. The closed upper bound prevents "row committed at `NOW()` during the extract query" from appearing in two adjacent runs. Without it, some rows are double-extracted (wasteful) or missed (data loss).
### 5.3 Idempotent load via natural unique keys
Every incremental bronze table needs a PRIMARY KEY or UNIQUE that matches the source's natural unique key. `ON CONFLICT DO NOTHING` makes re-running a CSV harmless. **Do not invent surrogate keys on bronze** — they defeat the ON CONFLICT guarantee. If the source has no natural key, fix the source or accept the table as a snapshot.
### 5.4 Transactional load boundary
Insert + watermark update + run-log update are one transaction. Splitting them creates "ghost" states where watermark advanced but rows didn't load, causing silent holes.
### 5.5 CSV audit trail — never delete
Moved-to-`processed/` CSVs are cheap ($0.023/GB/month on S3-class storage). They pay for themselves the first time you need to replay a window or debug a row-count mismatch.
### 5.6 PostGIS round-trip via EWKT
`ST_AsEWKT(geom)` on extract, `ST_GeomFromEWKT(ewkt)` on load. Preserves SRID inline. Do NOT store `ST_AsText` + separate SRID column — it doubles the chance of mismatch. Guard NULLs: `CASE WHEN geom IS NULL THEN NULL ELSE ST_AsEWKT(geom) END`.
### 5.7 Fail loud, fail early
Audit migrations (roles, constraints) should `RAISE EXCEPTION` with a bullet list of what's missing. Silent success is worse than noisy failure — a missing PK surfaces three months later as "why are there duplicate trips?".
---
## 6. Snapshot vs. Incremental Decision Matrix
| Signal | Snapshot (TRUNCATE + reload) | Incremental (watermark + append) |
|---|---|---|
| Row count | < ~10k | > ~10k |
| Meaning of "current state" | Matters | Doesn't matter; history matters |
| Deletes in source | Common | Rare |
| Update frequency per row | High | Low (append-mostly) |
| Natural unique key | May not exist | Must exist |
| Example | `devices`, `live_positions`, `geofences` | `position_history`, `trips`, `alarms`, event logs |
When in doubt: **snapshot is simpler**. Only escalate to incremental when the snapshot CSV would exceed a few MB per run.
---
## 7. Observability Contract
Every pipeline adds these three views to its control schema — no exceptions:
```sql
CREATE OR REPLACE VIEW <control>.v_table_freshness AS
SELECT table_name,
MAX(run_finished_at) AS last_loaded_at,
NOW() - MAX(run_finished_at) AS lag,
COUNT(*) FILTER (WHERE run_started_at > NOW() - INTERVAL '24 hours') AS loads_last_24h
FROM <control>.extract_runs
WHERE status = 'loaded'
GROUP BY table_name;
CREATE OR REPLACE VIEW <control>.v_recent_failures AS
SELECT run_id, table_name, run_started_at, run_finished_at, csv_path, error_message
FROM <control>.extract_runs
WHERE status = 'failed' AND run_started_at > NOW() - INTERVAL '24 hours'
ORDER BY run_started_at DESC;
CREATE OR REPLACE VIEW <control>.v_watermark_lag AS
SELECT table_name, last_extracted_at, last_loaded_at, rows_loaded_last_run,
NOW() - last_loaded_at AS load_lag,
NOW() - last_extracted_at AS extract_lag
FROM <control>.extract_watermarks;
```
Wire a Grafana alert on each view. Test the alert by manually failing a run before go-live.
---
## 8. Schema Drift Handling
Schema drift between source and bronze is inevitable. Two rules:
1. **Detect at design time.** Diff source DDL against bronze DDL before writing any extract SQL. Unit changes (metres vs. km), renamed columns, and added nullable columns are the usual suspects.
2. **Fix in the extract query, not the load.** Put all transformations in the SELECT so the CSV on disk already matches the bronze column names and units. The load workflow should be dumb — CSV column N goes to bronze column N.
Document every drift in the runbook (§5 of the operations runbook). Future developers WILL hit them.
---
## 9. Verification Gates
### Pre-deploy (before first cron tick)
- [ ] Every migration applied successfully.
- [ ] Control tables seeded (one watermark row per incremental table).
- [ ] Every credential's "Test connection" passes.
- [ ] Blob storage prefixes exist.
- [ ] Manual workflow trigger succeeds end-to-end for one table.
### First run (manual trigger of extract workflow)
- [ ] Every processed table has a row in `extract_runs` with `status='loaded'`.
- [ ] Row-count parity with source (± in-flight writes): `SELECT COUNT(*) FROM <source>` vs. `SELECT COUNT(*) FROM bronze.<table>`.
- [ ] Geometry columns round-trip cleanly: `SELECT ST_AsText(geom) FROM bronze.<table> LIMIT 5` returns valid POINTs.
- [ ] All CSVs moved from `exports/` to `processed/`.
### Steady-state (after 24h / first full schedule cycle)
- [ ] `v_table_freshness` shows lag < cadence × 2 for every table.
- [ ] `v_recent_failures` is empty.
- [ ] Row counts in bronze growing at expected rate.
Only declare "done" after all three gates pass.
---
## 10. Scheduling Calibration
Tradeoffs:
| Cadence | Pros | Cons |
|---|---|---|
| Every 15 min | Low lag, small CSVs | High orchestrator churn, noisy alerts |
| Every 3 h (recommended) | Predictable, fits ops windows, tolerable lag | Overnight backlog carries to morning |
| Nightly (once/day) | Cheap, simple | Unacceptable for real-time panels |
Rule of thumb: cadence = 2550% of your latency tolerance. 4h latency budget → 1-2h cadence.
Fold cadence around traffic patterns. Don't run 24× at 1-hour intervals if the source generates zero rows between midnight and 05:00.
---
## 11. Common Failure Modes & Recovery
| Failure | Symptom | Fix |
|---|---|---|
| CSV stuck in `exports/` | `v_recent_failures` has a row; CSV never moved | Next scheduled run retries automatically (idempotent). If persistent, open orchestrator logs by `run_id`. |
| Table marked `loading` for >1 cadence | n8n executor crashed mid-transaction | DB rolled back. Next run retries. If stuck >2 cadences, manually re-trigger the extract. |
| Row counts diverge > 1% | CSV parse error silently dropped rows | `rows_extracted != rows_loaded` in `extract_runs` — inspect the CSV for malformed rows. |
| Geometry loads as NULL | EWKT serialisation broke | Check for missing `CASE WHEN geom IS NULL` guard in extract SQL. |
| Distance/units 1000× wrong | Schema drift not caught | Check extract SQL for the unit conversion (see §8). |
**Back-fill a window:**
```sql
UPDATE <control>.extract_watermarks
SET last_extracted_at = NOW() - INTERVAL '24 hours'
WHERE table_name = '<table>';
```
Next run re-extracts the gap. `ON CONFLICT DO NOTHING` filters duplicates.
**Full reseed (nuclear):**
```sql
UPDATE <control>.extract_watermarks
SET last_extracted_at = '2000-01-01T00:00:00Z'
WHERE table_name = '<table>';
```
Next run back-fills all history in one very large CSV. Expected; it moves to `processed/` on success.
---
## 12. Security Baseline
- Two roles minimum: owner (writes) and RO (reads). Never use superuser from the orchestrator.
- `sslmode=require` on every public-IP DB connection.
- Passwords never in committed SQL — use placeholder tokens (`CHANGE_ME_BEFORE_APPLY`) and swap in-session during apply. Document rotation in the runbook.
- Blob storage credentials scoped to the project's prefix, not the whole bucket.
- Rotate all credentials before go-live (don't reuse the ones that were flying around in design conversations).
---
## 13. Reusability Checklist (Applying to a New Project)
When starting a new data project, copy the Tracksolid DWH layout and edit these points:
- [ ] Rename schemas: `<proj>_control` instead of `dwh_control` if multiple DWHs share a DB.
- [ ] Adjust `<proj>_owner` / `<proj>_ro` role names.
- [ ] Update bucket prefix: `s3://<bucket>/<project>/exports|processed/`.
- [ ] Re-do the snapshot/incremental decision for every source table (§6).
- [ ] Identify watermark columns and natural unique keys for every incremental table (§5.1, §5.3).
- [ ] Map schema drift before writing extract SQL (§8).
- [ ] Calibrate cadence to the new project's latency budget (§10).
- [ ] Ship the three observability views (§7) — even if nobody will look at them in week one.
- [ ] Write the runbook from the template: follow `docs/DWH_PIPELINE.md` section-for-section.
- [ ] Run the verification gates (§9) before declaring done.
---
## 14. Reference Implementation (Tracksolid DWH)
These files are the copy-paste template:
| File | Purpose |
|---|---|
| `dwh/260423_dwh_ddl_v1.sql` | Bronze DDL + roles + schemas |
| `dwh/261001_dwh_control.sql` | Control schema (watermarks + run log) |
| `dwh/261002_bronze_constraints_audit.sql` | ON CONFLICT key assertion |
| `dwh/261003_dwh_roles.sql` | Role contract assertion |
| `dwh/261004_dwh_observability_views.sql` | Freshness/failure/watermark views |
| `docs/DWH_PIPELINE.md` | Operations runbook (troubleshooting, manual re-run, rotation) |
| `docs/superpowers/specs/2026-04-24-n8n-dwh-bronze-pipeline-design.md` | Design spec (why each decision) |
| `docs/superpowers/plans/2026-04-24-n8n-dwh-bronze-pipeline.md` | Task-by-task implementation plan |
| `n8n-workflows/dwh_extract.json` | Extract workflow (reference) |
| `n8n-workflows/dwh_load_bronze.json` | Load workflow (reference) |
**For the next project, fork this manual first, then adapt.** Do not re-design from scratch — the seven design principles in §5 are the parts people keep getting wrong.

View file

@ -1,235 +0,0 @@
# pgbouncer sidecar deployment
**Date:** 2026-05-07
**Branch:** `quality-program-2026-04-12`
**Status:** Phase 1 deployed. Phase 2 (pgAdmin4 sidecar) was rolled back on 2026-05-08 — see git history (`bc020cb`, then reverted).
---
## Context
**Driver:** pgAdmin4 running on the maintainer's laptop has been exhausting
`tracksolid_db`'s `max_connections`. Each Query Tool tab in pgAdmin holds its
own long-lived backend connection; combined with the existing peak of ~5060
connections from the ingest pipeline, the budget tips over and cascades —
pgcli (and anything else trying to connect) starts failing.
**Goal:** Add pgbouncer in front of `timescale_db` to enforce a connection
budget via transaction-mode pooling. Desktop pgAdmin (or any other admin
client) connects through pgbouncer and is multiplexed onto a small fixed
pool of backends.
**Frozen scope (unchanged this round):**
- DWH bronze pipeline (`dwh/*.sql`, `tracksolid_dwh@31.97.44.246:5888`)
- n8n DWH workflows (`n8n-workflows/dwh_extract*`, `dwh_load_bronze*`)
- Grafana provisioning (`grafana/provisioning/datasources/...`)
- Python ingest containers (`ingest_movement_rev.py`, `ingest_events_rev.py`,
`webhook_receiver_rev.py`) — they keep talking to `timescale_db:5432`
directly. Cutover, if desired, is a separate plan.
- `db_backup` sidecar — `pg_dump` is incompatible with transaction-mode
pooling and stays on `timescale_db:5432`.
---
## Phase 1 — pgbouncer sidecar, no client cutover
Add a new service to `docker-compose.yaml`. Internal Docker network only;
no host port binding.
```yaml
pgbouncer:
image: edoburu/pgbouncer
restart: always
depends_on:
timescale_db:
condition: service_healthy
env_file: .env
environment:
- DB_HOST=timescale_db
- DB_PORT=5432
- DB_USER=${POSTGRES_USER}
- DB_PASSWORD=${POSTGRES_PASSWORD}
- DB_NAME=${POSTGRES_DB}
- POOL_MODE=transaction
- AUTH_TYPE=scram-sha-256
- MAX_CLIENT_CONN=200
- DEFAULT_POOL_SIZE=15
- MIN_POOL_SIZE=2
- RESERVE_POOL_SIZE=5
- SERVER_RESET_QUERY=DISCARD ALL
- SERVER_IDLE_TIMEOUT=600
- ADMIN_USERS=${POSTGRES_USER}
- LISTEN_PORT=6432
- AUTH_USER=pgbouncer
- AUTH_QUERY=SELECT uname, phash FROM public.user_lookup($$1)
healthcheck:
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -p 6432 -U ${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 3
```
**Why these values:**
- `POOL_MODE=transaction` — recycles backend on every transaction boundary.
Cuts pgAdmin's per-tab idle conn from 1 backend → ~0 when idle.
- `DEFAULT_POOL_SIZE=15` — total backend slots per (user, db) pair. Sits
comfortably under Postgres `max_connections` (default 100) leaving room for
ingest's existing ~5060.
- `MAX_CLIENT_CONN=200` — pgAdmin can open as many tabs as it wants; they
queue rather than fail.
- `RESERVE_POOL_SIZE=5` — emergency slack when `default_pool_size` saturates.
- `SERVER_RESET_QUERY=DISCARD ALL` — wipes session state between transactions
so leaked `SET`s from one client don't bleed into the next.
### Auth: SCRAM passthrough via `auth_query`
Avoids hand-maintaining `userlist.txt`. pgbouncer authenticates as a
dedicated `pgbouncer` Postgres role and looks up SCRAM hashes for the
requesting user via a SECURITY DEFINER function.
New migration `10_pgbouncer_auth.sql` (08 and 09 are taken by
`08_analytics_config.sql` and `09_trips_enrichment.sql`):
```sql
-- Role created with placeholder password; run_migrations.py:sync_role_passwords
-- replaces it with PGBOUNCER_AUTH_PASSWORD on every container startup.
-- Same convention used today for grafana_ro.
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'pgbouncer') THEN
CREATE ROLE pgbouncer LOGIN PASSWORD 'SET_PASSWORD_IN_ENV';
END IF;
END
$$;
CREATE OR REPLACE FUNCTION public.user_lookup(in_user text,
OUT uname text, OUT phash text) RETURNS record AS $$
BEGIN
SELECT usename, passwd FROM pg_catalog.pg_shadow
WHERE usename = in_user INTO uname, phash;
RETURN;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
REVOKE ALL ON FUNCTION public.user_lookup(text) FROM public;
GRANT EXECUTE ON FUNCTION public.user_lookup(text) TO pgbouncer;
```
Two changes to `run_migrations.py`:
1. Append `"10_pgbouncer_auth.sql"` to `MIGRATIONS`.
2. Extend `sync_role_passwords()` `roles` dict with
`"pgbouncer": os.getenv("PGBOUNCER_AUTH_PASSWORD")`.
The migration is applied by the next ingest container restart and recorded
in `tracksolid.schema_migrations`. `sync_role_passwords` then ALTER ROLEs
the password from the env var so the placeholder is never live.
### New env vars in `.env`
- `PGBOUNCER_AUTH_PASSWORD` — password for the new `pgbouncer` Postgres role
- (existing vars reused: `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`)
### Phase 1 verification
1. Apply migration via ingest container restart; confirm in
`tracksolid.schema_migrations` that `10_pgbouncer_auth.sql` is recorded.
2. `docker compose up -d pgbouncer`.
3. From inside any compose service:
```bash
psql -h pgbouncer -p 6432 -U postgres -d tracksolid_db -c 'SELECT 1'
```
4. From the pgbouncer container's admin console:
```bash
psql -h 127.0.0.1 -p 6432 -U postgres -d pgbouncer -c 'SHOW POOLS;'
```
Confirm pool mode = `transaction`, server connections within
`default_pool_size`.
5. `SHOW STATS;` and `SHOW CLIENTS;` should both respond.
6. Confirm no client has cut over: `tracksolid.ingestion_log` continues
accumulating; Grafana panels keep refreshing.
---
## Files to modify / create
| Path | Change |
|---|---|
| `260507_pgbouncer_deployment.md` | THIS FILE — runbook for the rollout |
| `docker-compose.yaml` | Add `pgbouncer` service |
| `10_pgbouncer_auth.sql` | NEW — creates `pgbouncer` role + `public.user_lookup` SECURITY DEFINER function |
| `.env` | Add `PGBOUNCER_AUTH_PASSWORD` (do not commit values) |
| `docs/CONNECTIONS.md` | Add a "pgbouncer" section: pool mode, exposure, who uses it, how to connect for ad-hoc admin |
| `CLAUDE.md` §3 / §4 | Note that admin tooling now goes through `pgbouncer:6432`; ingest/grafana/backup remain direct; reference this runbook |
## Files NOT to modify (frozen scope)
- `grafana/provisioning/datasources/tracksolid_postgres.yaml`
- `n8n-workflows/dwh_extract*.json`, `n8n-workflows/dwh_load_bronze*.json`
- `dwh/*.sql`
- `ingest_movement_rev.py`, `ingest_events_rev.py`, `webhook_receiver_rev.py`,
`ts_shared_rev.py`
- `backup/``pg_dump` keeps using `timescale_db:5432` directly
---
## Reused conventions and utilities
- `run_migrations.py` already applies new `NN_*.sql` files in order against
`tracksolid_db` and tracks them in `tracksolid.schema_migrations`. Phase 1
adds `10_pgbouncer_auth.sql` to this flow — no new tooling needed.
- `env_file: .env` + `depends_on: <svc> condition: service_healthy` mirrors
the existing pattern at `docker-compose.yaml:2831, 3942, 5053, 6770,
8790`.
- Container-name resolution rule from CLAUDE.md §3 still applies for any
`docker exec` against the new service:
```bash
docker ps --filter name=pgbouncer --format "{{.Names}}" | head -1
```
---
## Out-of-scope follow-ups (separate plans)
1. **Cut over Python ingest to pgbouncer.** Change `DATABASE_URL` in `.env`
from `timescale_db:5432` to `pgbouncer:6432`. Requires verifying psycopg2
pool + SAVEPOINTs against transaction-mode pgbouncer (low risk per
exploration — no LISTEN/NOTIFY, no advisory locks across statements, no
prepared statements in the codebase).
2. **Rotate `dwh_owner` / `grafana_ro` plaintext passwords** still in
`dwh/260423_dwh_ddl_v1.sql` (pre-existing item from CLAUDE.md §10).
---
## Rollback
If pgbouncer misbehaves:
1. **Stop the service without touching the rest of the stack:**
```bash
docker compose stop pgbouncer
docker compose rm -f pgbouncer
```
Ingest, Grafana, webhook, backup are unaffected — they were never cut
over.
2. **Revert the SQL migration if needed:**
```sql
DROP FUNCTION public.user_lookup(text);
DROP ROLE pgbouncer;
DELETE FROM tracksolid.schema_migrations
WHERE filename = '10_pgbouncer_auth.sql';
```
3. **Revert compose changes** by checking out the prior `docker-compose.yaml`.
---
## End-to-end verification checklist
- [ ] `10_pgbouncer_auth.sql` applied — visible in
`tracksolid.schema_migrations`
- [ ] `pgbouncer` service healthy — `docker compose ps` shows `healthy`
- [ ] `psql -h pgbouncer -p 6432 -U postgres -d tracksolid_db -c 'SELECT 1'`
from inside the network
- [ ] `SHOW POOLS;` in pgbouncer admin shows `transaction` mode
- [ ] Existing pipelines unaffected: `tracksolid.ingestion_log` continues
growing at current rate; Grafana dashboards still render
- [ ] pgcli no longer hits "too many connections" when used alongside pgAdmin

View file

@ -1,75 +0,0 @@
============================================================================
Device reconciliation — CSV vs tracksolid.devices
============================================================================
CSV file : 20260427_FSG_Vehicles_mitieng.csv
CSV row count : 162
DB row count : 172
Delta (DB-CSV) : +10
─ Per-account breakdown ─────────────────────────────────────────────────
account CSV DB delta
(blank) 0 10 +10
Fireside@HQ 52 52 +0
Fireside_MSA 41 41 +0
NULL 6 0 -6
fireside 63 69 +6
─ IMEIs in DB but NOT in CSV (10) ─────────────────────────────
imei account city last_synced_at device_name
359857081891921 JK Subaru KCS 903Y
359857082898297 KDK 829A GP
862798052707995 fireside 2026-04-27 19:30:53.484218+00:00 JC400P-07995
862798052715071 KDU 878T_CAM
862798052785751 fireside 2026-04-27 19:30:53.484218+00:00 JC400P-85751
862798052786270 fireside 2026-04-27 19:30:53.484218+00:00 JC400P-86270
865135061040349 KDU 878T_Track
865135061559405 X3-59405
865135061569172 fireside 2026-04-27 19:30:53.484218+00:00 X3-69172
865135061569529 fireside 2026-04-27 19:30:53.484218+00:00 X3-69529
─ IMEIs in CSV but NOT in DB (0) ─────────────────────────────
(none — every CSV row has a corresponding device row)
─ Devices in both, but DB metadata still NULL (162) ──────────────
Likely cause: import_drivers_csv.py has not been re-run with --apply
against the new CSV, or rows had 'Identification' placeholders.
imei blank_fields
353549090553685 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
353549090561720 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
353549090566281 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
353549090566885 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
353549090567685 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
353549090567701 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
359857081885410 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081886467 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, depot_address
359857081886871 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
359857081886905 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081887069 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081887192 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081891566 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081891590 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081891632 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081891798 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081892101 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081892309 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857081892440 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
359857081892762 assigned_city, cost_centre, assigned_route, vehicle_category, fuel_100km, depot_address, driver_name, vehicle_number
359857082037185 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082038977 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082040981 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082042052 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082042854 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082042953 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address, driver_name, vehicle_number
359857082044280 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082046145 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082896911 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
359857082897091 assigned_city, cost_centre, assigned_route, vehicle_category, vehicle_brand, fuel_100km, depot_address
... and 132 more
─ Suggested next step ───────────────────────────────────────────────────
Inspect the IMEIs above. Decide one of:
(a) Prune — delete from tracksolid.devices if they are stale test/decommissioned units.
(b) Leave-as-NULL — keep them as auto-synced API rows; their metadata stays NULL until added to a future CSV.
(c) Addendum — add them to the CSV (or a sidecar CSV) and re-run import_drivers_csv.py --apply.
Document the choice in 260427_device_reconciliation.md.

View file

@ -1,91 +0,0 @@
# Device Reconciliation — 162 vs 182 (2026-04-27)
Phase 0.2 of the Business Analytics redesign. Resolves the gap between
`20260427_FSG_Vehicles_mitieng.csv` (162 rows) and `tracksolid.devices`
(~182 rows at last check).
## How to populate this report
1. Pull this branch onto the Coolify host (or rebuild containers so the
ingest container has `audit_device_reconciliation.py`).
2. Run inside the ingest container so it has `DATABASE_URL`:
```bash
ING=$(docker ps --filter name=ingest_movement --format "{{.Names}}" | head -1)
docker cp 20260427_FSG_Vehicles_mitieng.csv "$ING":/app/
docker exec "$ING" python audit_device_reconciliation.py \
--csv 20260427_FSG_Vehicles_mitieng.csv \
--out /tmp/260427_audit_output.txt
docker cp "$ING":/tmp/260427_audit_output.txt ./
```
3. Paste the audit output into the **Audit output** section below.
4. Mark the chosen disposition for each IMEI in the **Disposition** section.
## Audit output
First run: 2026-04-27 23:35 UTC against `tracksolid_db` on stage. Full output in
`260427_audit_output.txt`. Headline numbers:
| Metric | Value |
|---|---|
| CSV rows | 162 |
| `tracksolid.devices` rows | 172 |
| Delta (DB CSV) | +10 |
| In CSV but not in DB | 0 |
| In DB but not in CSV | 10 |
| Devices both sides, DB metadata still NULL on ≥1 field | 162 (resolved by importer run) |
After running `import_drivers_csv.py --only-null --apply` (2026-04-27): 154
devices updated, 8 already complete, 0 inserted. Coverage now: `assigned_city`
152/172, `cost_centre` 150/172, `vehicle_brand` 2/172, `fuel_100km` 3/172.
`assigned_route` / `vehicle_category` / `depot_address` remain 0/172 (CSV
provided no values for these — Phase 1 follow-up).
The 10 in-DB-not-in-CSV IMEIs are listed in `260427_audit_output.txt`. They
sit in `(blank)` or `fireside` accounts and surface in Grafana as
`assigned_city = 'unassigned'` thanks to the existing COALESCE in
`07_analytics_views.sql`.
## Disposition
For each IMEI in the "in DB but not in CSV" list, choose one and record why:
| IMEI | Account | Last seen | Disposition | Notes |
|---|---|---|---|---|
| | | | | |
**Disposition options:**
- **prune** — Delete from `tracksolid.devices`. Use when the unit is a stale
test/decommissioned device that should never have synced. Capture the SQL
before running:
```sql
DELETE FROM tracksolid.devices WHERE imei = '<imei>';
```
*Caveat:* foreign keys from `position_history`, `trips`, `alarms` must be
considered first — these will block the delete if there's any history.
Usually safer to leave-as-NULL.
- **leave-as-NULL** — Keep the row; metadata fields stay NULL. The device
was auto-synced from a Tracksolid account that the CSV doesn't cover
(likely `Fireside@HQ` rows that were left out of this Mitieng export).
Grafana views already use `COALESCE(d.assigned_city, d.city, 'unassigned')`
so these surface as "unassigned" but don't break dashboards.
- **addendum** — Add to a follow-up CSV and re-run the importer with
`--apply`. Use when the device is legitimate fleet metadata was just
missing from the export.
## Decision
<!-- Fill in once dispositions are chosen. -->
- Total devices reviewed: ___
- Pruned: ___
- Left-as-NULL: ___
- Added via addendum: ___
After action, re-run `audit_device_reconciliation.py` and confirm the
delta is what you expect.

View file

@ -1,374 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tracksolid Stack — Engineering Review &amp; Improvement Plan (2026-06-01)</title>
<style>
:root {
--bg: #0f1115;
--panel: #171a21;
--panel-2: #1d212b;
--ink: #e6e9ef;
--ink-dim: #aab2c0;
--line: #2a2f3a;
--accent: #5b9dff;
--hi: #ff5d5d;
--med: #ffb454;
--lo: #5fd0a0;
--good: #5fd0a0;
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0; background: var(--bg); color: var(--ink);
font-family: var(--sans); line-height: 1.6; font-size: 16px;
}
.wrap { max-width: 980px; margin: 0 auto; padding: 48px 28px 96px; }
header.doc {
border-bottom: 1px solid var(--line); padding-bottom: 28px; margin-bottom: 36px;
}
.kicker { color: var(--accent); font-family: var(--mono); font-size: 13px; letter-spacing: .12em; text-transform: uppercase; }
h1 { font-size: 30px; line-height: 1.25; margin: 10px 0 14px; }
.meta { color: var(--ink-dim); font-size: 14px; }
.meta b { color: var(--ink); font-weight: 600; }
h2 { font-size: 22px; margin: 44px 0 8px; padding-top: 10px; border-top: 1px solid var(--line); }
h2 .num { color: var(--accent); font-family: var(--mono); margin-right: 10px; }
h3 { font-size: 17px; margin: 26px 0 6px; }
p { margin: 10px 0; }
a { color: var(--accent); }
code { font-family: var(--mono); font-size: .87em; background: var(--panel-2); padding: 1px 6px; border-radius: 4px; color: #d7e3ff; }
pre { background: #0b0d12; border: 1px solid var(--line); border-radius: 8px; padding: 14px 16px; overflow-x: auto; font-family: var(--mono); font-size: 13px; color: #cdd6e4; }
ul, ol { margin: 10px 0 10px 4px; padding-left: 22px; }
li { margin: 5px 0; }
.lead { color: var(--ink-dim); font-size: 16px; }
.callout { border-left: 3px solid var(--accent); background: var(--panel); border-radius: 0 8px 8px 0; padding: 14px 18px; margin: 18px 0; }
.callout.warn { border-left-color: var(--hi); }
.callout.warn b { color: var(--hi); }
.finding { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 4px 22px 18px; margin: 22px 0; }
.badge { display: inline-block; font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: .06em; padding: 3px 9px; border-radius: 999px; text-transform: uppercase; vertical-align: middle; margin-left: 8px; }
.b-hi { background: rgba(255,93,93,.15); color: var(--hi); border: 1px solid rgba(255,93,93,.35); }
.b-med { background: rgba(255,180,84,.13); color: var(--med); border: 1px solid rgba(255,180,84,.32); }
.b-lo { background: rgba(95,208,160,.12); color: var(--lo); border: 1px solid rgba(95,208,160,.3); }
.b-sec { background: rgba(91,157,255,.13); color: var(--accent); border: 1px solid rgba(91,157,255,.32); }
.ref { font-family: var(--mono); font-size: 12.5px; color: var(--ink-dim); }
table { width: 100%; border-collapse: collapse; margin: 18px 0; font-size: 14.5px; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--ink-dim); font-weight: 600; font-size: 12.5px; text-transform: uppercase; letter-spacing: .05em; }
td.up-h { color: var(--hi); font-weight: 600; }
td.up-m { color: var(--med); font-weight: 600; }
td.up-l { color: var(--lo); font-weight: 600; }
.pill { font-family: var(--mono); font-size: 11px; padding: 2px 7px; border-radius: 4px; background: var(--panel-2); color: var(--ink-dim); }
.good-box { border: 1px solid rgba(95,208,160,.3); background: rgba(95,208,160,.05); border-radius: 10px; padding: 6px 22px 16px; margin: 22px 0; }
.good-box h2 { border-top: none; color: var(--good); }
footer { margin-top: 60px; padding-top: 22px; border-top: 1px solid var(--line); color: var(--ink-dim); font-size: 13px; }
.toc { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 16px 22px; margin: 8px 0 0; }
.toc ol { margin: 6px 0; }
.toc a { text-decoration: none; }
.toc a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="wrap">
<header class="doc">
<div class="kicker">Engineering Review · Fireside Communications · Tracksolid Fleet Stack</div>
<h1>Database &amp; Microservice Assessment — Opportunities &amp; Refactoring</h1>
<p class="meta">
<b>Date:</b> 2026-06-01 &nbsp;·&nbsp;
<b>Reviewer:</b> Claude (Opus 4.8) &nbsp;·&nbsp;
<b>Scope:</b> TimescaleDB/PostGIS schema + migrations, and the three ingestion microservices
(<code>ingest_movement_rev.py</code>, <code>ingest_events_rev.py</code>, <code>webhook_receiver_rev.py</code> + shared <code>ts_shared_rev.py</code>)
</p>
<p class="meta">Findings are ordered by <b>greatest performance upside first</b>, as requested.</p>
</header>
<div class="callout warn">
<p><b>Access caveat — read this first.</b> The remote instance was <b>unreachable from the review environment</b>:
every probed port (22, 5433, 5432, 443) timed out, so the IP is not whitelisted (or the host was down).
I could <b>not</b> run <code>EXPLAIN</code>, read live row/chunk counts, confirm which indexes actually exist,
or inspect the running images. Everything below is a <b>static review</b> of the source and migration files.
Items needing live confirmation are tagged <span class="pill">verify live</span>.</p>
<p style="margin-bottom:0"><b>Immediate security note:</b> <code>.env</code> is <b>committed to git</b> (it is listed in
<code>.gitignore</code>, but was tracked before that rule existed, so the rule is a no-op). The live Tracksolid app
secret, the Postgres superuser password, and the Grafana admin password are all in the repo history on Forgejo.
Treat all three as compromised and rotate them.</p>
</div>
<div class="toc">
<strong>Findings</strong>
<ol>
<li><a href="#f1">Single-threaded scheduler holds a DB transaction open across throttled geocoding</a> <span class="badge b-hi">High</span></li>
<li><a href="#f2">dwh_gold daily-metrics ETL is non-functional</a> <span class="badge b-hi">High</span></li>
<li><a href="#f3">v_driver_aggregates_daily will not scale; safeguard not applied</a> <span class="badge b-hi">High</span></li>
<li><a href="#f4">pgbouncer deployed but bypassed by the application</a> <span class="badge b-med">Medium</span></li>
<li><a href="#f5">Migrations race across three containers with no lock</a> <span class="badge b-med">Medium</span></li>
<li><a href="#f6">Orphaned migration: 10_driver_clock_views.sql never applied</a> <span class="badge b-med">Medium</span></li>
<li><a href="#f7">Security gaps (webhook auth, committed secrets)</a> <span class="badge b-sec">Security</span></li>
<li><a href="#f8">Smaller DB-design notes</a> <span class="badge b-lo">Low</span></li>
<li><a href="#good">What's genuinely good</a></li>
<li><a href="#plan">Suggested order of attack</a></li>
</ol>
</div>
<!-- ====================== FINDING 1 ====================== -->
<h2 id="f1"><span class="num">1</span>Single-threaded scheduler holds a DB transaction open across throttled geocoding<span class="badge b-hi">Highest upside</span></h2>
<div class="finding">
<p><code>ingest_movement_rev.py</code> runs every job on one <code>schedule</code> thread
(<span class="ref">main(), lines 674695</span>). Within that, <code>poll_trips()</code> opens a transaction
(<span class="ref">with get_conn(), line 343</span>) and then, <b>inside that open transaction</b>, calls
<code>reverse_geocode()</code> twice per trip (<span class="ref">lines 392393</span>).
<code>reverse_geocode</code> enforces a global <b>1 request/second</b> Nominatim throttle
(<span class="ref">ts_shared_rev.py:463, _geocode_throttle</span>).</p>
<h3>Consequences</h3>
<ul>
<li>A batch of N new trips can hold a single pooled connection open for <b>N×~2 seconds</b> of network I/O — a
long-running transaction that pins a snapshot (bad for autovacuum's cleanup horizon) and ties up a connection.</li>
<li>Because the scheduler is one thread, while <code>poll_trips</code> is geocoding, the <b>60-second live-position
sweep cannot run</b>. The "live" freshness SLA silently degrades to minutes whenever trips/parking work through a
backlog. <code>poll_track_list</code> (30 min) and <code>poll_stale_locations</code> (10 min) share the same
thread and also block each other.</li>
<li>Every 15 min, <code>poll_trips</code> re-runs the 8-subquery enrichment block (<code>_ENRICH_QUERY</code>,
<span class="ref">lines 295321</span>) for the <b>entire last hour</b> of trips, even though the
<code>ON CONFLICT</code> mostly <code>COALESCE</code>s the result away.</li>
</ul>
<h3>Recommendation</h3>
<ul>
<li>Move geocoding <b>out of the DB transaction</b>: collect trip rows, commit, then geocode + <code>UPDATE</code>
in a second pass (or delegate geocoding to a queue / n8n).</li>
<li>Gate enrichment on <code>WHERE start_address IS NULL</code> so already-enriched trips don't re-pay the cost.</li>
<li>Run the 60s live sweep on its own thread/process so slow reporting jobs cannot starve it.
<code>schedule</code> + <code>time.sleep(1)</code> on one thread is the wrong concurrency model when one job is
latency-critical and others do long network I/O.</li>
</ul>
</div>
<!-- ====================== FINDING 2 ====================== -->
<h2 id="f2"><span class="num">2</span>The <code>dwh_gold</code> daily-metrics ETL is non-functional<span class="badge b-hi">High</span></h2>
<div class="finding">
<p><code>dwh_gold.refresh_daily_metrics()</code> (<span class="ref">migration 05, lines 212264</span>) selects
<code>t.imei AS vehicle_key</code> and inserts into <code>fact_daily_fleet_metrics.vehicle_key</code>, which is
<code>INTEGER REFERENCES dwh_gold.dim_vehicles(vehicle_key)</code> (<span class="ref">schema lines 237243</span>).
But <code>imei</code> is a 1215-digit <b>TEXT</b> string:</p>
<ul>
<li>15-digit IMEIs overflow <code>int4</code><em>"integer out of range"</em>.</li>
<li>Shorter ones violate the FK because <b>nothing ever populates <code>dim_vehicles</code></b> — no code path
inserts into it.</li>
</ul>
<p>So the function cannot succeed as written, and <code>v_utilisation_daily</code> (which joins
<code>fact → dim_vehicles → devices</code>, <span class="ref">migration 07, lines 268286</span>) will always be
empty. CLAUDE.md lists "schedule the nightly ETL" as a LOW open item — but scheduling it today would error on every
run.</p>
<p style="margin-bottom:0"><b>Recommendation:</b> redesign the gold layer around <code>imei</code> (drop the surrogate
key, or populate <code>dim_vehicles</code> from <code>devices</code> first and look up the key), and fix the column
type. This is a real bug hiding behind "not scheduled yet."</p>
</div>
<!-- ====================== FINDING 3 ====================== -->
<h2 id="f3"><span class="num">3</span><code>v_driver_aggregates_daily</code> will not scale, and the safeguard wasn't applied<span class="badge b-hi">High</span></h2>
<div class="finding">
<p>Migration 07 (<span class="ref">lines 159223</span>) builds this view with two 31-day scans of
<code>position_history</code> plus a <code>LAG()</code> window over <code>source='track_list'</code> rows. There is
<b>no index on <code>position_history.source</code></b>, and the only index on the hypertable is the
<code>(imei, gps_time)</code> primary key.</p>
<p>The view's own header comment says <em>"convert to a continuous aggregate once the hypertable exceeds ~100k rows."</em>
At 156 devices writing a row/minute from the poll sweep plus track_list waypoints, you cross 100k in <b>days</b>, not
months. <span class="pill">verify live</span> current row + chunk count.</p>
<p style="margin-bottom:0"><b>Recommendation:</b> build the speeding/harsh aggregates as a TimescaleDB continuous
aggregate (the pattern already exists in <code>v_mileage_daily_cagg</code>), or at minimum add a partial index
supporting the <code>source='track_list'</code> + time filter. As-is, the daily driver dashboard does a growing full
hypertable scan on every load.</p>
</div>
<!-- ====================== FINDING 4 ====================== -->
<h2 id="f4"><span class="num">4</span>pgbouncer is deployed but the application bypasses it entirely<span class="badge b-med">Medium</span></h2>
<div class="finding">
<p><code>docker-compose.yaml</code> adds a pgbouncer sidecar (<span class="ref">lines 82116</span>) "to cap
tracksolid_db connections," but <code>.env</code> sets
<code>DATABASE_URL=...@timescale_db:5432/...</code> — the Python pools connect <b>straight to Postgres</b>, not to
pgbouncer's 6432.</p>
<p>So the connection cap does nothing for the three services. The real ceiling today is the sum of per-process pools:</p>
<pre>webhook : uvicorn --workers 2 → 2 procs × ThreadedConnectionPool(max=12) = 24
ingest_movement = 12
ingest_events = 12
total ≈ 48 direct conns</pre>
<p>At 80156 devices this is not a live performance problem — it is wasted/contradictory infrastructure and an
intent-vs-reality gap. You also maintain a SCRAM-passthrough <code>user_lookup()</code> SECURITY DEFINER function
(<span class="ref">migration 10</span>) with no consumer.</p>
<p style="margin-bottom:0"><b>Recommendation:</b> either point <code>DATABASE_URL</code> at <code>pgbouncer:6432</code>
(transaction-pool mode disallows session features, but the code uses none beyond <code>client_encoding</code>), or
remove the sidecar.</p>
</div>
<!-- ====================== FINDING 5 ====================== -->
<h2 id="f5"><span class="num">5</span>Migrations race across three containers with no lock<span class="badge b-med">Medium · reliability</span></h2>
<div class="finding">
<p>All three services run <code>python run_migrations.py</code> on startup (<span class="ref">compose lines 26, 37,
48</span>) and start in parallel once the DB is healthy. <code>run_migrations.py</code> does check-then-act
(<code>already_applied()</code><code>run_file()</code>, <span class="ref">lines 231242</span>) with <b>no
advisory lock</b>. On a fresh database, three containers can pass <code>already_applied()==False</code>
simultaneously and run the same file.</p>
<ul>
<li>Migration 02's <code>CREATE TRIGGER</code> loop (<span class="ref">lines 255267</span>) has no
<code>IF NOT EXISTS</code> — concurrent runs throw, and <code>run_file()</code> treats any <code>ERROR:</code> as
fatal → <code>sys.exit(1)</code> → a service refuses to start.</li>
<li><code>run_file()</code> greps stderr for <code>ERROR:</code> without <code>-v ON_ERROR_STOP=1</code>, and files
02/03 have no <code>BEGIN/COMMIT</code>, so a mid-file failure can leave partial schema that later gets mis-seeded
as "applied."</li>
</ul>
<p style="margin-bottom:0"><b>Recommendation:</b> wrap the run in <code>pg_advisory_lock(&lt;const&gt;)</code> /
unlock, and run psql with <code>ON_ERROR_STOP=1</code>. Low effort, removes a class of cold-start flakiness.</p>
</div>
<!-- ====================== FINDING 6 ====================== -->
<h2 id="f6"><span class="num">6</span>Orphaned migration: <code>10_driver_clock_views.sql</code> is never applied<span class="badge b-med">Medium</span></h2>
<div class="finding">
<p>The runner's <code>MIGRATIONS</code> list (<span class="ref">run_migrations.py:2737</span>) includes
<code>10_pgbouncer_auth.sql</code> but <b>not</b> <code>10_driver_clock_views.sql</code>. Two files share the
<code>10_</code> prefix and the list is hand-maintained, so <code>v_driver_clock_daily/_today</code> (which the n8n
tardiness workflow depends on, per the file header) exist only if someone applied them by hand — they are not
reproducible from a clean deploy.</p>
<p style="margin-bottom:0"><b>Recommendation:</b> rename to <code>11_</code> and add to the list. Better: switch the
runner from a hardcoded list to globbing <code>NN_*.sql</code> sorted, so this cannot recur.</p>
</div>
<!-- ====================== FINDING 7 ====================== -->
<h2 id="f7"><span class="num">7</span>Security gaps worth fixing now<span class="badge b-sec">Security</span></h2>
<div class="finding">
<ul>
<li><b>Webhook auth is effectively off.</b> <code>_validate_token</code>
(<span class="ref">webhook_receiver_rev.py:8487</span>) skips validation entirely when
<code>JIMI_WEBHOOK_TOKEN</code> is empty, and it is <b>not set in <code>.env</code></b>. The push endpoints are
exposed via Traefik, so anyone who learns the URL can inject arbitrary telemetry/alarms (each <code>/pushgps</code>
accepts up to 5000 rows, no rate limit). Set the token and make an unset token <b>fail closed</b> in production.</li>
<li><b>Committed secrets</b> (see top banner). Rotate the Tracksolid app secret, Postgres password, and Grafana admin
password; <code>git rm --cached .env</code> and scrub history.</li>
<li><code>dwh/260423_dwh_ddl_v1.sql</code> plaintext passwords are an existing known item in CLAUDE.md — same class of
problem.</li>
</ul>
</div>
<!-- ====================== FINDING 8 ====================== -->
<h2 id="f8"><span class="num">8</span>Smaller DB-design notes<span class="badge b-lo">Low — queue these</span></h2>
<div class="finding">
<ul>
<li><b><code>v_mileage_daily_cagg</code> is built on a column that's mostly NULL.</b> It computes
<code>MAX(current_mileage) - MIN(current_mileage)</code> (<span class="ref">schema lines 293301</span>), but
<code>current_mileage</code> is only populated by the poll sweep — <code>track_list</code> and <code>/pushgps</code>
inserts leave it NULL, and odometer resets/device swaps produce negative or huge deltas. The aggregate's
<code>dist_km</code> is unreliable. Prefer deriving daily distance from <code>trips.distance_km</code>.</li>
<li><b><code>ingestion_log</code> has no retention and no index.</b> <code>v_ingestion_health</code> does
<code>DISTINCT ON (endpoint) … ORDER BY endpoint, run_at DESC</code> over the whole table, which grows ~875
rows/day forever. Add <code>(endpoint, run_at DESC)</code> plus a retention/partition policy.</li>
<li><b>Alarm dedup is leaky on the poll path.</b> <code>alarms_dedup UNIQUE (imei, alarm_type, alarm_time)</code>
(<span class="ref">schema line 199</span>) — the poll path inserts <code>alertTypeId</code> as
<code>alarm_type</code> with no NOT-NULL guard, and <code>NULL</code> defeats the unique constraint
(<code>NULL ≠ NULL</code>), so a null-type alarm can duplicate. The webhook path guards this; the poll path
doesn't.</li>
<li><b><code>live_positions</code>/staleness queries are seq scans</b> (no index on <code>gps_time</code>) — totally
fine at ~156 rows today; just don't carry that pattern into anything that scans <code>position_history</code>.</li>
<li><b>Dead/ambiguous code in <code>_parse_request</code></b> (<span class="ref">webhook lines 90143</span>): the
JSON-array branch <code>_parse_data_list</code> is never reached (it always falls through to
<code>request.form()</code>); harmless but misleading given the docstring claims it handles both.</li>
</ul>
</div>
<!-- ====================== GOOD ====================== -->
<div class="good-box">
<h2 id="good" style="border-top:none;"><span class="num" style="color:var(--good)"></span>What's genuinely good</h2>
<p>So this is balanced — the bones are solid:</p>
<ul>
<li>Per-row <code>SAVEPOINT</code> isolation so one bad item can't abort a batch.</li>
<li>Time-guarded upserts via the shared <code>upsert_live_position</code> helper.</li>
<li>Batched <code>execute_values</code> on the high-volume push / track-list paths.</li>
<li>Hypertables with compression + retention policies.</li>
<li>Parameterized SQL throughout — no injection surface.</li>
<li>Clean signal handling and pool teardown.</li>
<li>Idempotent migrations with a tracking table and <code>COMMENT ON VIEW</code> provenance.</li>
<li><code>sync_devices</code> N+1 already parallelized with a bounded thread pool.</li>
</ul>
<p style="margin-bottom:0">The issues above are mostly about <b>coupling</b>, <b>one broken ETL</b>, and
<b>scale-ahead-of-indexing</b> — not a bad foundation.</p>
</div>
<!-- ====================== PLAN ====================== -->
<h2 id="plan"><span class="num">»</span>Suggested order of attack (effort vs. upside)</h2>
<table>
<thead>
<tr><th style="width:38px">#</th><th>Action</th><th style="width:130px">Upside</th><th style="width:80px">Effort</th></tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Pull geocoding out of the trips transaction + gate on <code>start_address IS NULL</code>; isolate the 60s sweep on its own thread</td>
<td class="up-h">High — restores live freshness, frees connections</td>
<td>M</td>
</tr>
<tr>
<td>2</td>
<td>Fix or redesign <code>refresh_daily_metrics</code> / <code>dim_vehicles</code> (imei vs int key)</td>
<td class="up-h">High — unblocks all utilisation reporting</td>
<td>M</td>
</tr>
<tr>
<td>3</td>
<td>Convert <code>v_driver_aggregates_daily</code> to a continuous aggregate (or add <code>source</code>+time index)</td>
<td class="up-h">High and growing</td>
<td>M</td>
</tr>
<tr>
<td>4</td>
<td>Set <code>JIMI_WEBHOOK_TOKEN</code>; rotate + untrack <code>.env</code></td>
<td class="up-h">High (security)</td>
<td>S</td>
</tr>
<tr>
<td>5</td>
<td>Advisory-lock the migration runner + <code>ON_ERROR_STOP=1</code>; add <code>10_driver_clock_views</code> / switch to glob</td>
<td class="up-m">Medium (reliability)</td>
<td>S</td>
</tr>
<tr>
<td>6</td>
<td>Decide pgbouncer in-or-out; point <code>DATABASE_URL</code> accordingly</td>
<td class="up-m">Medium (clarity)</td>
<td>S</td>
</tr>
<tr>
<td>7</td>
<td><code>ingestion_log</code> index + retention; fix poll-path alarm null dedup; fix cagg distance source</td>
<td class="up-l">Lowmedium</td>
<td>S</td>
</tr>
</tbody>
</table>
<div class="callout">
<p style="margin:0"><b>Next step for live confirmation:</b> if I can get onto the box (whitelist the review IP for
5433, or an SSH tunnel), I'll confirm the <span class="pill">verify live</span> items — actual
<code>position_history</code> row/chunk counts, which indexes really exist, whether <code>refresh_daily_metrics</code>
has ever succeeded, and <code>EXPLAIN ANALYZE</code> on the heavier views — and tighten the priority order with real
numbers.</p>
</div>
<footer>
Generated 2026-06-01 by Claude (Opus 4.8) for Fireside Communications · Tracksolid Fleet Intelligence.
Static review only — no live database access was available at review time. File references use
<span class="ref">file:line</span> against the repository state on branch
<code>quality-program-2026-04-12</code>.
</footer>
</div>
</body>
</html>

View file

@ -1,47 +0,0 @@
# ops schema purge — pre-drop backup (2026-06-05)
Snapshot taken immediately before dropping the `ops` schema + `tracksolid.dispatch_log`
+ the dependent view `tracksolid.v_sla_inflight`. The dispatch/SLA/workshop features were
never implemented and are being purged (may take a different direction later).
Only two `ops` tables held rows, and both are **migration-08 seed data**
(`migrations/08_analytics_config.sql`), i.e. regenerable — this file is belt-and-suspenders.
Every other ops table (`tickets`, `service_log`, `odometer_readings`) and the view
`vw_service_forecast` were empty. `tracksolid.dispatch_log` was empty.
## ops.cost_rates (3 rows)
| rate_key | scope_type | scope_value | metric | amount | currency | effective_from | notes |
|---|---|---|---|---|---|---|---|
| fuel.nairobi | city | nairobi | fuel_per_litre | 195.00 | KES | 2026-04-27 | Placeholder pump price — confirm with Finance. |
| fuel.mombasa | city | mombasa | fuel_per_litre | 195.00 | KES | 2026-04-27 | Placeholder pump price — confirm with Finance. |
| fuel.kampala | city | kampala | fuel_per_litre | 5200.00 | UGX | 2026-04-27 | Placeholder pump price — confirm with Finance. |
## ops.kpi_targets (12 rows)
| target_id | kpi_key | scope_type | scope_value | target | amber | red | direction | effective_from | notes |
|---|---|---|---|---|---|---|---|---|---|
| 1 | utilisation_pct | global | | 70.00 | 60.00 | 50.00 | higher_is_better | 2026-04-27 | Fleet utilisation: drive_hours / engine_on_hours. |
| 2 | idle_pct | global | | 15.00 | 20.00 | 25.00 | lower_is_better | 2026-04-27 | Idle as % of engine-on time. |
| 3 | idle_pct | cost_centre | osp patrol | 15.00 | 20.00 | 25.00 | lower_is_better | 2026-04-27 | OSP patrol idle target — same as global until calibrated. |
| 4 | fuel_kes_per_100km | global | | 12.00 | 14.00 | 16.00 | lower_is_better | 2026-04-27 | Fuel litres per 100km equivalent — uses fuel_100km on devices. |
| 5 | mttr_hours | global | | 4.00 | 6.00 | 8.00 | lower_is_better | 2026-04-27 | Mean Time To Resolve, field-service ticket. |
| 6 | alarms_per_100km | global | | 2.00 | 3.00 | 5.00 | lower_is_better | 2026-04-27 | Safety event density. |
| 7 | utilisation_pct | global | | 70.00 | 60.00 | 50.00 | higher_is_better | 2026-05-01 | Fleet utilisation: drive_hours / engine_on_hours. |
| 8 | idle_pct | global | | 15.00 | 20.00 | 25.00 | lower_is_better | 2026-05-01 | Idle as % of engine-on time. |
| 9 | idle_pct | cost_centre | osp patrol | 15.00 | 20.00 | 25.00 | lower_is_better | 2026-05-01 | OSP patrol idle target — same as global until calibrated. |
| 10 | fuel_kes_per_100km | global | | 12.00 | 14.00 | 16.00 | lower_is_better | 2026-05-01 | Fuel litres per 100km equivalent — uses fuel_100km on devices. |
| 11 | mttr_hours | global | | 4.00 | 6.00 | 8.00 | lower_is_better | 2026-05-01 | Mean Time To Resolve, field-service ticket. |
| 12 | alarms_per_100km | global | | 2.00 | 3.00 | 5.00 | lower_is_better | 2026-05-01 | Safety event density. |
## What was dropped
```sql
DROP VIEW IF EXISTS tracksolid.v_sla_inflight; -- depended on ops.tickets + dispatch_log
DROP SCHEMA IF EXISTS ops CASCADE; -- tickets, service_log, odometer_readings,
-- cost_rates, kpi_targets, vw_service_forecast
DROP TABLE IF EXISTS tracksolid.dispatch_log; -- empty; only fed v_sla_inflight
```
**Not dropped in this step:** `dwh_gold` schema and `tracksolid.v_utilisation_daily`
(separate decision, pending).

View file

@ -1,75 +0,0 @@
# Fleet Registry — Outstanding Data-Quality Issues
**Date:** 2026-06-08 · **Source:** `tracksolid.devices` (verified live) · **Scope:** 181 devices → 80 vehicles
**Urgency:** 🔴 **RED** = fix now (blocks ops / safety / visibility) · 🟠 **AMBER** = fix soon (accountability, classification, data trust) · 🟡 **YELLOW** = cleanup.
> ## ⭐ Biggest single fix: run the driver/plate CSV import
> Most items below are **missing source fields**. The prepared **`import_drivers_csv.py --apply`** has **not been run** (`vehicle_category` still 0/181, device count still 181). Running it — or entering the fields at source in the Tracksolid Pro portal — clears the bulk of this list at once.
---
## 🔴 RED — fix now
**R1. No driver phone — 175 / 181 (97%).** Dispatch/escalation can't contact a driver; only 6 are reachable. → Capture mobiles. **Owner:** Operations + Engineering (import).
**R2. 6 vehicles have NO GPS tracker** (dashcam only → invisible on the live map, no trips/mileage): `KCN 496A · KCQ 215F · KCU 237Z · KDM 306S · KDN 759G · KCZ 199P`. → Field-check; install/repair or decommission. **Owner:** Field ops.
**R3. 37 fully-unidentified devices being tracked** (no plate, model, or driver; "unknown" status). → Match serial/IMEI to a vehicle or decommission. **Owner:** Field ops + Engineering.
---
## 🟠 AMBER — fix soon
**A1. No driver name — 41 / 181 (23%).** Trips/speeding/idle can't be attributed → no accountability. → Assign drivers at source. **Owner:** Operations. *(CSV covers most.)*
**A2. 16 vehicles have a tracker but NO dashcam** — no incident/safety video (all 8 motorbikes, the Uganda units, several Proboxes). → Decide which need a camera; schedule installs. **Owner:** Field ops.
**A3. No vehicle model — 40 / 181 (22%).** Forces guesswork on the field-service vs specialist split. → Set `vehicle_models` at source. **Owner:** Operations. *(CSV covers most.)*
**A4. Duplicate plates corrupting the count:**
- `KDS 453Y` entered twice — `KDS 453Y` (tracker) + `KDS 453 Y` (camera, stray space).
- `KCC 199P` vs `KCZ 199P` — both pick-ups, both driver *Mbuvi Kioko*, one tracker + one camera → almost certainly **one vehicle under two plates**.
→ Correct the plate in the portal, then re-sync. **Owner:** Operations.
**A5. Two plates disagree with themselves (model conflict):**
| Plate | Tracker says | Camera says | Driver |
|---|---|---|---|
| KCY 080X | Pick-Up | Probox | Lawrence Kijogi |
| KCZ 223P | Pick-Up | Probox | Felix Muema |
→ Confirm the real type; set both devices to match. **Owner:** Operations.
**A6. `assigned_city` unreliable → regional reporting suspect.** 4 vehicles show two cities (e.g. KDC 490Q: Mombasa/Nairobi; KCY 838X: Mombasa/Voi) — it's inherited from the account, not the vehicle. → Set per vehicle. **Owner:** Operations + Engineering.
---
## 🟡 YELLOW — cleanup
**Y1. Placeholder driver names** — `Garage` (×4), `UG` (×2), `Management_Mazda` (×2), `Parked` (×1). → Replace with real names or a clear "unassigned" convention. **Owner:** Operations.
**Y2. Missing SIM (26) and cost-centre (31).** → Backfill from records/CSV. **Owner:** Operations + Engineering.
**Y3. `vehicle_category` empty (0 / 181).** Low urgency — the map/KPIs derive the segment from `vehicle_models` automatically. → Optional; CSV fills it. **Owner:** Engineering.
---
## Action plan
| # | Tier | Issue | Action | Owner | Cleared by CSV import? |
|---|---|---|---|---|---|
| R1 | 🔴 | No driver phone (97%) | Capture mobiles | Ops + Eng | ✅ mostly |
| R2 | 🔴 | 6 vehicles, no GPS tracker | Field-check / install | Field ops | — |
| R3 | 🔴 | 37 unidentified devices | Identify or decommission | Field ops + Eng | ✅ partly |
| A1 | 🟠 | No driver name (23%) | Assign drivers | Ops | ✅ mostly |
| A2 | 🟠 | 16 vehicles, no dashcam | Schedule installs | Field ops | — |
| A3 | 🟠 | No vehicle model (22%) | Set model at source | Ops | ✅ mostly |
| A4 | 🟠 | Duplicate plates (KDS 453Y; KCC/KCZ 199P) | Fix plate, re-sync | Ops | — |
| A5 | 🟠 | Model conflicts (KCY 080X, KCZ 223P) | Confirm type | Ops | partial |
| A6 | 🟠 | Unreliable assigned_city | Set per vehicle | Ops + Eng | ✅ yes |
| Y1 | 🟡 | Placeholder driver names | Replace | Ops | partial |
| Y2 | 🟡 | Missing SIM (26) / cost-centre (31) | Backfill | Ops + Eng | ✅ mostly |
| Y3 | 🟡 | vehicle_category empty | Optional populate | Eng | ✅ yes |
**Suggested order:** (1) run/validate the **CSV import** — clears R1, R3(part), A1, A3, A6, Y2, Y3; (2) field-ops sweep for **R2 + A2** (tracker/camera hardware); (3) Operations fixes **A4/A5 plates + Y1** in the portal; (4) re-run the scan to confirm.

File diff suppressed because it is too large Load diff

View file

@ -1,5 +0,0 @@
What I'd skip (for now)
- ML/forecasting sections until 6+ months of trip data exist — with 3 recorded trips, anything is noise.
- Temperature, fuel-theft, OBD-RPM queries — already gated behind webhook registration in §8; duplicating them in §3 just adds clutter.
- Route-optimisation queries — that's a separate product, not an analytics-doc addition.

File diff suppressed because it is too large Load diff

View file

@ -1,320 +0,0 @@
# n8n DWH Bronze Layer Pipeline — Design & Plan
**Date:** 2026-04-24
**Status:** Awaiting approval
**Repo:** `/Users/davidkiania/Downloads/55_ts_coolify_gemini_prod`
---
## Context
Fireside's Tracksolid fleet pipeline currently ingests telemetry into a single production DB (`tracksolid_db`, TimescaleDB/PostGIS on Coolify at `stage.rahamafresh.com`). There is no downstream data warehouse, so every analytical query hits the live operational DB — risking contention as Grafana panels and ad-hoc analysis scale. A full medallion-architecture bronze DDL exists on disk (`dwh/260423_dwh_ddl_v1.sql`) but has never been populated.
The user wants to build the **first layer of that DWH** using n8n (already running on the same Coolify instance, already connected to both source and target DBs). The design has two n8n workflows:
1. **Workflow 1 — Extract**: pull tables from the source `tracksolid_db` (Coolify-hosted TimescaleDB, reached via the same internal Docker network n8n is on), write CSVs to rustfs blob storage.
2. **Workflow 2 — Load**: pick up those CSVs and upsert into the bronze schema inside `tracksolid_dwh` (PostGIS) on the separate server `31.97.44.246:5888`.
**Confirmed connection targets:**
- **Source:** `tracksolid_db` on the Coolify stack — n8n connects via internal Docker network (trial confirmed working).
- **Target:** `tracksolid_dwh` at `31.97.44.246:5888` — a separate PostGIS instance. Schemas `bronze`, `silver`, `gold`, plus `dwh_control` all live in this one database.
The intermediate rustfs CSV layer (a) gives a durable audit trail of every extract, (b) decouples source-DB availability from target-DB availability (a remote-DB outage doesn't lose data — the CSV waits in `exports/`), and (c) matches how rustfs is already used in the stack (pg_dump backups).
---
## Architecture
```
┌──────────────────────────────────────────────────┐
│ n8n (Coolify instance) │
│ │
│ Workflow 1: dwh_extract │
│ Schedule: cron 0 5,8,11,14,17,20,23 * * * │
│ (Africa/Nairobi, 7 runs/day) │
│ Steps per table: │
│ 1. Read watermark from target control table │
│ 2. Query source with watermark bounds │
│ 3. Render rows as CSV │
│ 4. Upload CSV to rustfs │
│ 5. Insert row into dwh_control.extract_runs │
│ (status='uploaded') │
│ 6. Execute Workflow 2 for this CSV │
│ │
│ Workflow 2: dwh_load_bronze │
│ Trigger: Execute Workflow (from Workflow 1) │
│ Input: { table, csv_path, run_id, │
│ run_started_at } │
│ Steps: │
│ 1. Download CSV from rustfs │
│ 2. Parse CSV │
│ 3. BEGIN │
│ INSERT ... ON CONFLICT DO NOTHING │
│ UPDATE extract_watermarks │
│ UPDATE extract_runs SET status='loaded' │
│ COMMIT │
│ 4. Move CSV: dwh/exports/ → dwh/processed/ │
└──────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
tracksolid_db rustfs (fleet-db) tracksolid_dwh (PostGIS)
(Coolify internal) /dwh/exports/ 31.97.44.246:5888
/dwh/processed/ dwh_control.extract_watermarks
dwh_control.extract_runs
bronze.devices
bronze.position_history
bronze.trips
bronze.alarms
bronze.parking_events
bronze.device_events
bronze.live_positions
bronze.ingestion_log
```
**Rustfs path convention:**
- Active export: `s3://fleet-db/dwh/exports/{table}/{YYYYMMDD_HHMM}_EAT.csv`
- After successful load: moved to `s3://fleet-db/dwh/processed/{table}/{YYYYMMDD_HHMM}_EAT.csv`
- Never deleted — this is the audit trail.
---
## Table-by-Table Extraction Strategy
### Snapshot tables (TRUNCATE + full reload every run)
Small state-based tables where "current state" matters, not history.
| Source table | Rows | Bronze target |
|---|---|---|
| `tracksolid.devices` | 63 | `bronze.devices` |
| `tracksolid.live_positions` | 19 | `bronze.live_positions` |
**Load pattern:**
```sql
BEGIN;
TRUNCATE bronze.devices;
INSERT INTO bronze.devices (...) VALUES (...);
UPDATE dwh_control.extract_watermarks SET last_loaded_at = NOW() WHERE table_name='devices';
COMMIT;
```
### Incremental tables (watermark + append-with-dedup)
Append-only event/history tables. Watermark is the **DB insertion timestamp**, not the device-reported timestamp, so out-of-order device clocks / delayed pushes can't cause silent data loss.
| Source table | Watermark column | Natural unique key (exists in source) | Bronze conflict target |
|---|---|---|---|
| `tracksolid.position_history` | `recorded_at` | `(imei, gps_time)` | `(imei, gps_time)` |
| `tracksolid.trips` | `updated_at` | `(imei, start_time)` | `id` |
| `tracksolid.alarms` | `updated_at` | `(imei, alarm_type, alarm_time)` | `id` |
| `tracksolid.parking_events` | `updated_at` | `(imei, start_time, event_type)` | `id` |
| `tracksolid.device_events` | `created_at` | `(imei, event_type, event_time)` | `id` |
| `tracksolid.ingestion_log` | `run_at` | PK `id` | `id` |
**Extract pattern (closed upper bound to avoid boundary drift):**
```sql
SELECT <cols>, ST_AsEWKT(geom) AS geom_ewkt
FROM tracksolid.position_history
WHERE recorded_at > :last_extracted_at
AND recorded_at <= :run_started_at
ORDER BY recorded_at;
```
**Load pattern (idempotent):**
```sql
BEGIN;
INSERT INTO bronze.position_history (imei, gps_time, geom, lat, lng, ...)
SELECT imei, gps_time, ST_GeomFromEWKT(geom_ewkt), lat, lng, ...
FROM csv_stage
ON CONFLICT (imei, gps_time) DO NOTHING;
UPDATE dwh_control.extract_watermarks
SET last_extracted_at = :run_started_at,
last_loaded_at = NOW(),
rows_loaded_last_run = <count>
WHERE table_name = 'position_history';
UPDATE dwh_control.extract_runs
SET status = 'loaded', run_finished_at = NOW(), rows_loaded = <count>
WHERE run_id = :run_id;
COMMIT;
```
### First-run behaviour
`extract_watermarks` seeded with `last_extracted_at = '2026-01-01T00:00:00Z'` so the first run back-fills all historical data in a single CSV per table.
### Skipped for now (no data, webhooks pending)
`obd_readings`, `fault_codes`, `fuel_readings`, `temperature_readings`, `lbs_readings`, `heartbeats` — add later by copying the incremental pattern and seeding a watermark row.
---
## PostGIS Geometry Handling
Six source tables have `geometry(Point, 4326)` columns: `live_positions`, `position_history`, `trips` (start+end), `parking_events`, `alarms`.
- **Extract:** `ST_AsEWKT(geom) AS geom_ewkt` — preserves SRID inline (`SRID=4326;POINT(...)`)
- **Load:** `ST_GeomFromEWKT(csv.geom_ewkt)` — no separate SRID step, no loss on round-trip
- **NULL safety:** `CASE WHEN geom IS NULL THEN NULL ELSE ST_AsEWKT(geom) END`
---
## Control Tables (to add to `tracksolid_dwh`)
New migration file: `dwh/261001_dwh_control.sql` — applied once to `tracksolid_dwh@31.97.44.246:5888`.
```sql
CREATE SCHEMA IF NOT EXISTS dwh_control;
CREATE TABLE dwh_control.extract_watermarks (
table_name TEXT PRIMARY KEY,
last_extracted_at TIMESTAMPTZ NOT NULL DEFAULT '2026-01-01T00:00:00Z',
last_loaded_at TIMESTAMPTZ,
rows_loaded_last_run INT,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE dwh_control.extract_runs (
run_id BIGSERIAL PRIMARY KEY,
table_name TEXT NOT NULL,
run_started_at TIMESTAMPTZ NOT NULL,
run_finished_at TIMESTAMPTZ,
rows_extracted INT,
rows_loaded INT,
csv_path TEXT,
status TEXT CHECK (status IN ('extracting','uploaded','loading','loaded','failed')),
error_message TEXT
);
CREATE INDEX idx_extract_runs_table_time ON dwh_control.extract_runs (table_name, run_started_at DESC);
CREATE INDEX idx_extract_runs_status_time ON dwh_control.extract_runs (status, run_finished_at DESC);
-- Seed one row per incremental table
INSERT INTO dwh_control.extract_watermarks (table_name) VALUES
('position_history'), ('trips'), ('alarms'),
('parking_events'), ('device_events'), ('ingestion_log');
```
---
## Scheduling
- **Cron:** `0 5,8,11,14,17,20,23 * * *` with TZ `Africa/Nairobi` (set in n8n schedule node).
- **7 runs/day:** 05:00, 08:00, 11:00, 14:00, 17:00, 20:00, 23:00 EAT.
- **Fits the 68/day requirement** with even 3-hour gaps in daytime and a silent overnight window (23:00 → 05:00 = 6h) which is fine because device traffic is minimal after hours.
- First run of each day (05:00) will carry the overnight backlog — this is the expected behaviour of the watermark design.
---
## Error Handling & Observability
### Per-table isolation
Workflow 1 iterates tables in sequence; a failure on one table does not block others. Every table's result (success or failure) is logged to `dwh_control.extract_runs`.
### Retryable failures
If Workflow 2 fails mid-load: transaction rolls back → watermark stays → CSV stays in `exports/` → next scheduled run re-processes it (natural retry).
### Alerting (Grafana panels on `tracksolid_dwh`, read via `dwh_ro` role — see below)
- **Freshness:** `SELECT table_name, NOW() - MAX(run_finished_at) AS lag FROM dwh_control.extract_runs WHERE status='loaded' GROUP BY 1 HAVING NOW() - MAX(run_finished_at) > INTERVAL '4 hours';`
- **Failures in last hour:** `SELECT * FROM dwh_control.extract_runs WHERE status='failed' AND run_started_at > NOW() - INTERVAL '1 hour';`
- **Row count sanity:** `rows_extracted != rows_loaded` flags CSV parse or load issues.
### n8n-level error workflow
Attach an "Error Workflow" in both n8n workflows that posts to a webhook (existing pattern in `n8n-workflows/`) for immediate notification.
---
## Security & Credentials
Both DB credentials already exist in n8n (connections trialled and working). The required credential shapes are:
| n8n credential | Host / Port / DB | Recommended user | Usage |
|---|---|---|---|
| `tracksolid_source` | Coolify internal `timescale_db:5432` → DB `tracksolid_db` | `grafana_ro` (read-only) | Source extract queries |
| `tracksolid_dwh_target` | `31.97.44.246:5888` → DB `tracksolid_dwh` | `dwh_owner` (scoped) | Bronze writes + control-table updates |
| `rustfs_s3` | `${RUSTFS_ENDPOINT}` | `${RUSTFS_ACCESS_KEY}` | CSV upload/download/move |
### Credential-hardening recommendations (current state vs target state)
The trial connection string uses `postgres` (superuser) over a public IP. Two hardening steps to take before production:
1. **Create a scoped `dwh_owner` role** on `tracksolid_dwh` — owns only `bronze` + `dwh_control` schemas, cannot touch other DBs or cluster roles. n8n's `tracksolid_dwh_target` credential switches to this user.
2. **Create a `dwh_ro` role** for Grafana panels — read-only across `bronze` + `dwh_control`. This is what the freshness/failure dashboards in §Error Handling use.
3. **Enforce `sslmode=require`** on the `tracksolid_dwh_target` connection string (public-IP hop, cleartext otherwise).
4. **Rotate the `postgres` password** that was shared in chat history — one-off cleanup, not a plan blocker.
All four are one-migration-file tasks and fit naturally into the `dwh/261001_dwh_control.sql` setup step.
---
## Files to Create / Modify
| Path | Action | Purpose |
|---|---|---|
| `dwh/261001_dwh_control.sql` | **new** | Control-schema migration (watermarks + run log) |
| `dwh/260423_dwh_ddl_v1.sql` | **review** | Confirm bronze tables have matching unique constraints; patch if missing |
| `n8n-workflows/dwh_extract.json` | **new** | Workflow 1 export |
| `n8n-workflows/dwh_load_bronze.json` | **new** | Workflow 2 export |
| `docs/DWH_PIPELINE.md` | **new** | Operations runbook (see verification section) |
| `CLAUDE.md` §3, §4, §5, §10 | **update** | Add `tracksolid_dwh@31.97.44.246:5888` to §3 Connection Params; add bronze schema + n8n DWH workflows to codebase map; remove DWH item from Open Items |
**Existing utilities to reuse (do NOT reinvent):**
- Rustfs env vars already wired in `docker-compose.yaml` (`RUSTFS_ENDPOINT`, `RUSTFS_ACCESS_KEY`, `RUSTFS_SECRET_KEY`, `RUSTFS_BUCKET`) — Workflow nodes read from the same `.env`.
- Backup rustfs client logic in `backup/backup_db.sh` is the reference pattern for S3 auth shape.
- Existing n8n workflow pattern in `n8n-workflows/jimi_pushgps.json` et al. for webhook trigger + HTTP-forward shape.
---
## Verification
### Pre-deployment checks (before first cron trigger)
1. **Bronze DDL applied:** `psql -h 31.97.44.246 -p 5888 -U dwh_owner -d tracksolid_dwh -c "\dt bronze.*"` lists 16 tables.
2. **Control schema applied:** same connection, `\dt dwh_control.*` lists `extract_watermarks`, `extract_runs`.
3. **Watermarks seeded:** `SELECT * FROM dwh_control.extract_watermarks;` returns 6 rows, all with `last_extracted_at = 2026-01-01`.
4. **Roles created:** `\du` lists `dwh_owner` and `dwh_ro`; `postgres` superuser no longer used for n8n.
5. **n8n credentials:** Test each credential individually in n8n UI — all three connect successfully (source via internal network, target via `31.97.44.246:5888` with `sslmode=require`).
6. **Rustfs path exists:** `aws --endpoint ${RUSTFS_ENDPOINT} s3 ls s3://fleet-db/dwh/` — if missing, create `exports/` and `processed/` prefixes.
### First-run verification (manually trigger Workflow 1)
1. `SELECT * FROM dwh_control.extract_runs ORDER BY run_id DESC LIMIT 20;` — 8 rows (one per table processed), all `status='loaded'`.
2. `SELECT table_name, rows_loaded_last_run FROM dwh_control.extract_watermarks;` — non-zero for all incremental tables that have source data.
3. Row-count parity:
```sql
-- on source (tracksolid_db, Coolify internal)
SELECT COUNT(*) FROM tracksolid.position_history;
-- on target (tracksolid_dwh @ 31.97.44.246:5888)
SELECT COUNT(*) FROM bronze.position_history;
```
Numbers should match ± rows inserted in the narrow window between the two queries.
4. **Geometry round-trip check:**
```sql
SELECT ST_AsText(geom) FROM bronze.position_history LIMIT 5;
-- should return valid POINT(lng lat) values, not NULL or garbage
```
5. **Rustfs audit:** `aws s3 ls s3://fleet-db/dwh/processed/` — 8 CSV files present (one per table), originals no longer in `exports/`.
### Steady-state verification (after 24h / 7 runs)
1. `SELECT table_name, NOW() - MAX(run_finished_at) FROM dwh_control.extract_runs WHERE status='loaded' GROUP BY 1;` — max lag < 3h 15min for every table.
2. `SELECT COUNT(*) FROM dwh_control.extract_runs WHERE status='failed';` — zero.
3. Grafana dashboard (to be added in a follow-up plan) shows freshness and row counts per table.
---
## Out of Scope (follow-up work)
- Silver/gold layer transformations (the DWH DDL defines schemas but no queries yet).
- Bronze schema evolution tooling (manual migrations are acceptable for one pipeline).
- Backfill of tables where webhooks aren't yet registered (OBD, fuel, temperature, LBS).
- Grafana dashboard panels for the DWH — worth its own spec once we have a week of data to design around.
---
## Open Questions (none blocking)
All design decisions resolved in the brainstorming session. Confirmed:
- Source: `tracksolid_db` on Coolify, reached via internal Docker network.
- Target: `tracksolid_dwh` at `31.97.44.246:5888` (public IP), schemas `bronze`/`silver`/`gold` + `dwh_control`.
- Trial connections already working in n8n.
If any endpoint/credential changes during implementation, those are n8n-credential updates only — no design change.

View file

@ -1,367 +0,0 @@
-- =============================================================
-- TRACKSOLID DWH SETUP & PERMISSIONS
-- Target Database: tracksolid_dwh
-- =============================================================
-- 1. EXTENSIONS
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION IF NOT EXISTS postgis; -- REQUIRED for geometry(Point,4326) columns
-- 2. ROLE CREATION (Idempotent)
-- SECURITY: Passwords below are placeholders. Before applying this file:
-- 1. Generate two strong secrets (e.g. `openssl rand -hex 24`)
-- 2. Replace both CHANGE_ME_BEFORE_APPLY tokens in-session (do NOT commit real values)
-- 3. Store the generated secrets in the n8n / Grafana credential stores only
-- Rotation: `ALTER ROLE <role> PASSWORD '<new secret>'` as a superuser.
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'dwh_owner') THEN
CREATE ROLE dwh_owner WITH LOGIN PASSWORD 'CHANGE_ME_BEFORE_APPLY';
END IF;
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'grafana_ro') THEN
CREATE ROLE grafana_ro WITH LOGIN PASSWORD 'CHANGE_ME_BEFORE_APPLY';
END IF;
END$$;
-- Grant database connection
GRANT CONNECT ON DATABASE tracksolid_dwh TO dwh_owner;
GRANT CONNECT ON DATABASE tracksolid_dwh TO grafana_ro;
-- 3. SCHEMAS
CREATE SCHEMA IF NOT EXISTS bronze AUTHORIZATION dwh_owner;
CREATE SCHEMA IF NOT EXISTS silver AUTHORIZATION dwh_owner;
CREATE SCHEMA IF NOT EXISTS gold AUTHORIZATION dwh_owner;
ALTER DATABASE tracksolid_dwh SET search_path TO bronze, silver, gold, public;
-- 4. PERMISSIONS & DEFAULT PRIVILEGES (Critical for Security & Automation)
-- Schema access
GRANT USAGE, CREATE ON SCHEMA bronze TO dwh_owner;
GRANT USAGE, CREATE ON SCHEMA silver TO dwh_owner;
GRANT USAGE, CREATE ON SCHEMA gold TO dwh_owner;
GRANT USAGE ON SCHEMA bronze TO grafana_ro;
GRANT USAGE ON SCHEMA silver TO grafana_ro;
GRANT USAGE ON SCHEMA gold TO grafana_ro;
GRANT USAGE ON SCHEMA public TO dwh_owner, grafana_ro;
-- Existing table access for Grafana
GRANT SELECT ON ALL TABLES IN SCHEMA bronze TO grafana_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA silver TO grafana_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA gold TO grafana_ro;
-- FUTURE table access: Any table created by dwh_owner will automatically be readable by grafana_ro
ALTER DEFAULT PRIVILEGES FOR ROLE dwh_owner IN SCHEMA bronze GRANT SELECT ON TABLES TO grafana_ro;
ALTER DEFAULT PRIVILEGES FOR ROLE dwh_owner IN SCHEMA silver GRANT SELECT ON TABLES TO grafana_ro;
ALTER DEFAULT PRIVILEGES FOR ROLE dwh_owner IN SCHEMA gold GRANT SELECT ON TABLES TO grafana_ro;
-- 5. BRONZE SCHEMA TABLES
-- Run as dwh_owner to ensure correct ownership & default privileges apply
SET ROLE dwh_owner;
SET search_path TO bronze, public;
-- 5.1 DEVICES (Slowly Changing Dimension - Type 2 handled in Silver)
CREATE TABLE IF NOT EXISTS bronze.devices (
imei TEXT PRIMARY KEY,
device_name TEXT,
mc_type TEXT,
mc_type_use_scope TEXT,
vehicle_name TEXT,
vehicle_number TEXT,
vehicle_models TEXT,
vehicle_icon TEXT,
vin TEXT,
engine_number TEXT,
vehicle_brand TEXT,
fuel_100km NUMERIC(6,2),
driver_name TEXT,
driver_phone TEXT,
sim TEXT,
iccid TEXT,
imsi TEXT,
account TEXT,
customer_name TEXT,
device_group_id TEXT,
device_group TEXT,
activation_time TIMESTAMPTZ,
expiration TIMESTAMPTZ,
enabled_flag SMALLINT DEFAULT 1 NOT NULL,
status TEXT DEFAULT 'active'::text,
city TEXT,
current_mileage_km NUMERIC(12,2),
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
last_synced_at TIMESTAMPTZ,
vehicle_category TEXT,
cost_centre TEXT,
assigned_route TEXT,
depot_geom geometry(Point,4326),
depot_address TEXT,
assigned_city TEXT,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.2 POSITION HISTORY (High-volume fact table)
CREATE TABLE IF NOT EXISTS bronze.position_history (
imei TEXT NOT NULL,
gps_time TIMESTAMPTZ NOT NULL,
geom geometry(Point,4326),
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
speed NUMERIC(7,2),
direction NUMERIC(6,2),
acc_status TEXT,
satellite SMALLINT,
current_mileage NUMERIC(12,2),
recorded_at TIMESTAMPTZ DEFAULT now(),
altitude NUMERIC(8,2),
post_type SMALLINT,
source TEXT DEFAULT 'poll'::text,
ingested_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (imei, gps_time)
);
-- 5.3 TRIPS (Aggregated fact table)
CREATE TABLE IF NOT EXISTS bronze.trips (
id BIGINT NOT NULL,
imei TEXT NOT NULL,
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ,
start_geom geometry(Point,4326),
end_geom geometry(Point,4326),
distance_km NUMERIC(12,2),
avg_speed_kmh NUMERIC(7,2),
max_speed_kmh NUMERIC(7,2),
updated_at TIMESTAMPTZ DEFAULT now(),
fuel_consumed_l NUMERIC(8,2),
idle_time_s INTEGER,
driving_time_s INTEGER,
trip_seq INTEGER,
source TEXT DEFAULT 'poll'::text,
ingested_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (id)
);
-- 5.4 ALARMS (Event log fact table)
CREATE TABLE IF NOT EXISTS bronze.alarms (
id BIGINT PRIMARY KEY,
imei TEXT,
alarm_type TEXT,
alarm_time TIMESTAMPTZ,
geom geometry(Point,4326),
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
speed NUMERIC(7,2),
acc_status TEXT,
updated_at TIMESTAMPTZ DEFAULT now(),
alarm_name TEXT,
source TEXT DEFAULT 'poll'::text,
severity TEXT,
geofence_id TEXT,
geofence_name TEXT,
acknowledged_at TIMESTAMPTZ,
acknowledged_by TEXT,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.5 DEVICE EVENTS (Connection lifecycle)
CREATE TABLE IF NOT EXISTS bronze.device_events (
id BIGINT PRIMARY KEY,
imei TEXT NOT NULL,
event_type TEXT NOT NULL,
event_time TIMESTAMPTZ NOT NULL,
timezone TEXT,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.6 DISPATCH LOG (Operational/SLA tracking)
CREATE TABLE IF NOT EXISTS bronze.dispatch_log (
dispatch_id BIGINT PRIMARY KEY,
ticket_id TEXT NOT NULL,
imei TEXT NOT NULL,
driver_name TEXT,
job_lat DOUBLE PRECISION NOT NULL,
job_lng DOUBLE PRECISION NOT NULL,
job_geom geometry(Point,4326),
assigned_at TIMESTAMPTZ DEFAULT now() NOT NULL,
first_movement_at TIMESTAMPTZ,
on_site_at TIMESTAMPTZ,
resolved_at TIMESTAMPTZ,
cancelled_at TIMESTAMPTZ,
distance_km NUMERIC(8,2),
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.7 FAULT CODES (OBD/DTC diagnostics)
CREATE TABLE IF NOT EXISTS bronze.fault_codes (
id BIGINT PRIMARY KEY,
imei TEXT NOT NULL,
reported_at TIMESTAMPTZ NOT NULL,
fault_code TEXT NOT NULL,
status_flags INTEGER,
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
geom geometry(Point,4326),
event_time TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.8 FUEL READINGS
CREATE TABLE IF NOT EXISTS bronze.fuel_readings (
imei TEXT NOT NULL,
reading_time TIMESTAMPTZ NOT NULL,
sensor_path TEXT,
value NUMERIC(10,3),
unit TEXT,
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
geom geometry(Point,4326),
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (imei, reading_time)
);
-- 5.9 GEOFENCES (Dimension/Reference)
CREATE TABLE IF NOT EXISTS bronze.geofences (
id BIGINT PRIMARY KEY,
fence_id TEXT,
fence_name TEXT NOT NULL,
fence_type TEXT,
geom geometry(Geometry,4326),
radius_m NUMERIC(10,2),
description TEXT,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.10 HEARTBEATS (Device health/ping)
CREATE TABLE IF NOT EXISTS bronze.heartbeats (
imei TEXT NOT NULL,
gate_time TIMESTAMPTZ NOT NULL,
power_level SMALLINT,
gsm_signal SMALLINT,
acc_status SMALLINT,
power_status SMALLINT,
fortify SMALLINT,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (imei, gate_time)
);
-- 5.11 INGESTION LOG (Metadata for tracking loads)
CREATE TABLE IF NOT EXISTS bronze.ingestion_log (
id BIGINT PRIMARY KEY,
run_at TIMESTAMPTZ DEFAULT now() NOT NULL,
endpoint TEXT NOT NULL,
imei_count INTEGER DEFAULT 0 NOT NULL,
rows_upserted INTEGER DEFAULT 0 NOT NULL,
rows_inserted INTEGER DEFAULT 0 NOT NULL,
duration_ms INTEGER DEFAULT 0 NOT NULL,
success BOOLEAN DEFAULT true NOT NULL,
error_code TEXT,
error_message TEXT,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.12 LBS READINGS (Fallback positioning)
CREATE TABLE IF NOT EXISTS bronze.lbs_readings (
id BIGINT PRIMARY KEY,
imei TEXT NOT NULL,
gate_time TIMESTAMPTZ NOT NULL,
post_type TEXT,
lbs_data JSONB,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.13 LIVE POSITIONS (Current state snapshot)
CREATE TABLE IF NOT EXISTS bronze.live_positions (
imei TEXT PRIMARY KEY,
geom geometry(Point,4326),
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
pos_type TEXT,
confidence SMALLINT,
gps_time TIMESTAMPTZ,
hb_time TIMESTAMPTZ,
speed NUMERIC(7,2),
direction NUMERIC(6,2),
acc_status TEXT,
gps_signal SMALLINT,
gps_num SMALLINT,
elec_quantity NUMERIC(5,2),
power_value NUMERIC(5,2),
battery_power_val NUMERIC(5,2),
tracker_oil TEXT,
temperature NUMERIC(8,2),
current_mileage NUMERIC(12,2),
device_status TEXT,
expire_flag TEXT,
activation_flag TEXT,
loc_desc TEXT,
recorded_at TIMESTAMPTZ DEFAULT now() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.14 OBD READINGS (Vehicle diagnostics)
CREATE TABLE IF NOT EXISTS bronze.obd_readings (
id BIGINT PRIMARY KEY,
imei TEXT,
reading_time TIMESTAMPTZ,
engine_rpm INTEGER,
fuel_level_pct NUMERIC(5,2),
updated_at TIMESTAMPTZ DEFAULT now(),
car_type SMALLINT,
acc_state SMALLINT,
status_flags INTEGER,
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
geom geometry(Point,4326),
obd_data JSONB,
coolant_temp_c NUMERIC(6,2),
battery_voltage NUMERIC(5,2),
intake_pressure NUMERIC(6,2),
throttle_pct NUMERIC(5,2),
vehicle_speed NUMERIC(7,2),
engine_load_pct NUMERIC(5,2),
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.15 PARKING EVENTS
CREATE TABLE IF NOT EXISTS bronze.parking_events (
id BIGINT PRIMARY KEY,
imei TEXT NOT NULL,
event_type TEXT,
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ,
duration_seconds INTEGER,
geom geometry(Point,4326),
address TEXT,
updated_at TIMESTAMPTZ DEFAULT now(),
ingested_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5.16 TEMPERATURE READINGS (Cold chain sensors)
CREATE TABLE IF NOT EXISTS bronze.temperature_readings (
imei TEXT NOT NULL,
reading_time TIMESTAMPTZ NOT NULL,
temperature NUMERIC(6,2),
humidity_pct NUMERIC(5,2),
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
ingested_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (imei, reading_time)
);
-- Reset role back to superuser
RESET ROLE;
RESET search_path;
-- 6. VERIFICATION GRANTS (Ensure Grafana can query immediately)
GRANT SELECT ON ALL TABLES IN SCHEMA bronze TO grafana_ro;
GRANT USAGE ON SCHEMA bronze TO grafana_ro;

View file

@ -1,163 +0,0 @@
"imei","device_name","mc_type","mc_type_use_scope","vehicle_name","vehicle_number","vehicle_models","vehicle_icon","vin","engine_number","vehicle_brand","fuel_100km","driver_name","driver_phone","sim","iccid","imsi","account","customer_name","device_group_id","device_group","activation_time","expiration","enabled_flag","status","city","current_mileage_km","created_at","updated_at","last_synced_at","vehicle_category","cost_centre","assigned_route","depot_geom","depot_address","assigned_city"
"353549090553685","Daniel Omondi - KMFF 099Z","AT4","personal","KMFF 099Z","KMFF 099Z","Motorbike","mtc",NULL,NULL,NULL,NULL,"Robert","0112794067","759336150","89254021334258404099","639021335840409","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-09-23 05:50:30+00","2040-09-23 23:59:59+00",1,"1",NULL,"2354.70","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"353549090561720","Wireless_Git","AT4","personal",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0701211913","89254021374215155053","639021371515505","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2025-06-09 09:12:50+00","2035-06-09 23:59:59+00",1,"1",NULL,"5992.43","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"353549090566281","KDR 592N","AT4","personal",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0797680464","89254021334258159693","639021335815969","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2024-11-08 04:01:30+00","2034-11-08 23:59:59+00",1,"1",NULL,"7771.90","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"353549090566885","Wireless GPS","AT4","personal",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0768445963","89254021334212352574","639021331235257","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2024-10-15 13:16:57+00","2034-10-15 23:59:59+00",1,"1",NULL,"17036.41","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"353549090567685","Daniel Kipkirui - KMFF 162Z","AT4","personal","KMFF 162Z","KMFF 162Z","Motorbike","mtc",NULL,NULL,NULL,NULL,"edwine","0112795498","742532058","89254021264260388966","639021266038896","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-09-23 05:09:39+00","2040-09-23 23:59:59+00",1,"1",NULL,"462.33","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"353549090567701","Wireless","AT4","personal",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0790176094","89254021394215205906","639021391520590","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2024-11-08 04:04:44+00","2034-11-08 23:59:59+00",1,"1",NULL,"16896.20","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081885410","Allan Owana - KDK 780K","GT06E","aotomobile","KDK 780K","KDK 780K","Probox","automobile",NULL,NULL,NULL,NULL,"Allan Owana",NULL,"703616117","89254021234222499854","639021232249985","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-19 09:32:22+00","2039-06-19 23:59:59+00",1,"1",NULL,"128853.11","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081886467","Gideon Kiprono - KCQ 215F","GT06E","aotomobile","KCQ 215F","OHS","Probox","automobile",NULL,NULL,NULL,"0.00","Gideon Kiprono",NULL,"746763076","89254021084186499865","639021088649986","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2019-06-30 09:30:00+00","2039-06-30 23:59:59+00",1,"1",NULL,"141057.46","2026-04-23 10:56:37.983314+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081886871","Kamonde KBA 467S","GT06E","aotomobile",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0746763083","89254021084186499873","639021088649987","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-30 09:09:14+00","2039-06-30 23:59:59+00",1,"1",NULL,"74183.36","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081886905","Kennedy Chege - KCQ 618K","GT06E","aotomobile","KCQ 618K","KCQ 618K","Probox","automobile",NULL,NULL,NULL,NULL,"Kennedy Chege",NULL,"746763132","89254021084186499923","639021088649992","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2019-06-30 07:08:35+00","2039-06-30 23:59:59+00",1,"1",NULL,"215608.19","2026-04-23 10:35:37.678371+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081887069","Wright Oseko - KCG 668W","GT06E","aotomobile","KCG 668W","KCG 668W","Probox","automobile",NULL,NULL,NULL,NULL,"Wright Oseko",NULL,"746763106","89254021084186499915","639021088649991","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2019-06-30 06:17:43+00","2039-06-30 23:59:59+00",1,"1",NULL,"239001.19","2026-04-23 11:00:08.769463+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081887192","Ndegwa Dancun - KCG 669W","GT06E","aotomobile","KCG 669W","KCG 669W","Probox","automobile",NULL,NULL,NULL,NULL,"Ndegwa Dancun",NULL,"746760191","89254021084186499501","639021088649950","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2019-06-15 10:26:15+00","2039-06-15 23:59:59+00",1,"1",NULL,"199191.85","2026-04-23 10:34:29.074112+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081891566","Simon Kamau - KCE 090R","GT06E","aotomobile","KCE 090R","KCE 090R","Probox","automobile",NULL,NULL,NULL,NULL,"Simon Kamau",NULL,"746760404","89254021084186499527","639021088649952","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2019-06-16 07:06:15+00","2039-06-16 23:59:59+00",1,"1",NULL,"215592.36","2026-04-23 10:30:55.739184+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081891590","Garage - KCE 699F","GT06E","aotomobile","KCE 699F","KCE 699F","Probox","automobile",NULL,NULL,NULL,NULL,"Garage",NULL,"746760215","89254021084186499519","639021088649951","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2019-06-16 11:11:24+00","2039-06-16 23:59:59+00",1,"1",NULL,"207814.05","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081891632","John Ondego - KCA 542Q","GT06E","aotomobile","KCA 542Q","KCA 542Q","Probox","automobile",NULL,NULL,NULL,NULL,"John Ondego",NULL,"746760038","89254021084186499485","639021088649948","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-15 09:17:53+00","2039-06-15 23:59:59+00",1,"1",NULL,"178914.47","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081891798","Garage - KCH 167M","GT06E","aotomobile","KCH 167M","KCH 167M","Probox","automobile",NULL,NULL,NULL,NULL,"Garage",NULL,"746760102","89254021084186499493","639021088649949","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-16 10:18:57+00","2039-06-16 23:59:59+00",1,"1",NULL,"168840.95","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081892101","Cornelius Kimutai - KCU 938R","GT06E","aotomobile","KCU 938R","KCU 938R","Van","automobile",NULL,NULL,NULL,NULL,"Cornelius Kimutai",NULL,"746759919","89254021084186499451","639021088649945","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2019-06-12 08:13:48+00","2039-06-12 23:59:59+00",1,"1",NULL,"149558.50","2026-04-23 10:29:21.507861+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081892309","Nicholas Erastus - KCQ 581M","GT06E","aotomobile","KCQ 581M","KCQ 581M","Probox","automobile",NULL,NULL,NULL,NULL,"Nicholas Erastus",NULL,"700023776","89254021084178504672","639021087850467","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2019-06-09 09:39:40+00","2039-06-09 23:59:59+00",1,"1",NULL,"209105.89","2026-04-23 10:40:40.169684+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081892440","KAZ 489Z","GT06E","aotomobile",NULL,NULL,NULL,"bus",NULL,NULL,NULL,NULL,NULL,NULL,"0700023806","89254021084178504698","639021087850469","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-09 10:04:39+00","2039-06-09 23:59:59+00",1,"1",NULL,"38197.20","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857081892762","Nicholas","GT06E","aotomobile",NULL,NULL,"Station Wagon","bus",NULL,NULL,"Toyota",NULL,NULL,NULL,"0746760503","89254021274233125361","639021273312536","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2019-06-16 08:31:46+00","2039-06-16 23:59:59+00",1,"1",NULL,"51048.97","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082037185","Amani Kazungu - KCY 084X","GT06E","aotomobile","KCY 084X","KCY 084X","Probox","automobile",NULL,NULL,NULL,NULL,"Amani Kazungu",NULL,"757338522","89254021154287000597","639021158700059","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-07-13 09:42:28+00","2040-07-13 23:59:59+00",1,"1",NULL,"172298.81","2026-04-23 10:51:08.665273+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082038977","Wilfred Kinyanjui - KCU 729C","GT06E","aotomobile","KCU 729C","KCU 729C","Crane","truck",NULL,NULL,NULL,NULL,"Wilfred Kinyanjui",NULL,"110094469","89254021164215938057","639021161593805","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-04-05 09:26:00+00","2040-04-05 23:59:59+00",1,"1",NULL,"172487.09","2026-04-23 10:24:33.914628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082040981","Amani Sulubu - KCY 090X","GT06E","aotomobile","KCY 090X","KCY 090X","Probox","automobile",NULL,NULL,NULL,NULL,"Amani Sulubu",NULL,"793375853","89254021064168004164","639021066800416","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-07-13 07:25:16+00","2040-07-13 23:59:59+00",1,"1",NULL,"166028.15","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082042052","Gabriel Musumba - KCE 690F","GT06E","aotomobile","KCE 690F","KCE 690F","Probox","automobile",NULL,NULL,NULL,NULL,"Gabriel Musumba",NULL,"110094466","89254021164215938024","639021161593802","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2020-04-03 17:30:13+00","2040-04-03 23:59:59+00",1,"1",NULL,"192693.23","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082042854","Elias Baya - KCZ 476E","GT06E","aotomobile","KCZ 476E","KCZ 476E","Probox","automobile",NULL,NULL,NULL,NULL,"Elias Baya",NULL,"110941187","89254021164224352993","639021162435299","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-08-09 05:06:42+00","2040-08-09 23:59:59+00",1,"1",NULL,"217595.68","2026-04-23 10:33:56.216621+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082042953","KCU 865Q Vanguard",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-23 13:24:33.293453+00","2026-04-23 13:24:33.293453+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"359857082044280","Lawrence Kijogi - KCY 080X","GT06E","aotomobile","KCY 080X","KCY 080X","Probox","automobile",NULL,NULL,NULL,NULL,"Lawrence Kijogi",NULL,"708155933","89254029851005131222","639029850513122","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-07-13 11:05:02+00","2040-07-13 11:05:02+00",1,"1",NULL,"169740.37","2026-04-23 14:52:58.983571+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082046145","Joseph Kabandi - KCY 076X","GT06E","aotomobile","KCY 076X","KCY 076X","Probox","automobile",NULL,NULL,NULL,NULL,"Joseph Kabandi",NULL,"110850007","89254021164223447158","639021162344715","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-07-13 08:31:26+00","2040-07-13 23:59:59+00",1,"1",NULL,"122254.48","2026-04-23 10:47:40.895504+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082896911","Hamisi Pande - KDD 689Y","GT06E","aotomobile","KDD 689Y","KDD 689Y","Probox","automobile",NULL,NULL,NULL,NULL,"Hamisi Pande",NULL,"112714612","89254021214211314660","639021211131466","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-09-17 11:50:53+00","2041-09-17 23:59:59+00",1,"1",NULL,"163435.74","2026-04-23 10:26:09.922447+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082897091","Peter Mbugua - KDK 728K","GT06E","aotomobile","KDK 728K","KDK 728K","Probox","automobile",NULL,NULL,NULL,NULL,"Peter Mbugua",NULL,"790262984","89254021234222500396","639021232250039","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-12-14 11:31:57+00","2042-12-14 23:59:59+00",1,"1",NULL,"131109.26","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082897257","Cassius Wakiyo - KDB 323M","GT06E","aotomobile","KDB 323M","KDB 323M","Probox","automobile",NULL,NULL,NULL,NULL,"Cassius Wakiyo",NULL,"746428882","89254021234222500818","639021232250081","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-08-29 15:07:26+00","2041-08-29 15:07:26+00",1,"1",NULL,"121688.92","2026-04-23 10:28:26.388654+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082897737","John Makori - KDB 585E","GT06E","aotomobile","KDB 585E","KDB 585E","Probox","automobile",NULL,NULL,NULL,NULL,"John Makori",NULL,"114596734","89254021214211145262","639021211114526","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-08-29 14:29:28+00","2041-08-29 14:29:28+00",1,"1",NULL,"156765.03","2026-04-23 10:38:57.445964+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082897794","Mutuku Joseph - KDC 739F","GT06E","aotomobile","KDC 739F","KDC 739F","Probox","automobile",NULL,NULL,NULL,NULL,"Mutuku Joseph","115019037","115019037","89254021224222632356","639021222263235","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-04-10 14:55:32+00","2041-04-10 14:55:32+00",1,"1",NULL,"205169.79","2026-04-23 10:30:22.530563+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082898008","Samuel Ng'ang'a - KDE 264M","GT06E","aotomobile","KDE 264M","KDE 264M","Probox","automobile",NULL,NULL,NULL,NULL,"Samuel Ng'ang'a",NULL,"711731539","89254021264260342245","639021266034224","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-10-28 09:43:11+00","2041-10-28 23:59:59+00",1,"1",NULL,"126584.24","2026-04-23 11:35:59.816581+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082898016","Job Ngare - KDM 309S","GT06E","aotomobile","KDM 309S","KDM 309S","Probox","automobile",NULL,NULL,NULL,NULL,"Job Ngare",NULL,"706895756","89254021324273007563","639021327300756","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-08-15 13:45:26+00","2033-08-15 23:59:59+00",1,"1",NULL,"107726.56","2026-04-23 11:20:25.939244+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082898073","Mutuku Antony - KDK 732K","GT06E","aotomobile","KDK 732K","KDK 732K","Probox","automobile",NULL,NULL,NULL,NULL,"Mutuku Antony",NULL,"793026954","89254021234222387539","639021232238753","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-12-20 06:33:12+00","2042-12-20 23:59:59+00",1,"1",NULL,"82096.79","2026-04-23 14:52:07.094447+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082898487","Dan Watila - KDE 638J","GT06E","aotomobile","KDE 638J","KDE 638J","Probox","automobile",NULL,NULL,NULL,NULL,"Dan Watila",NULL,"116242996","89254021334258404214","639021335840421","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-10-21 15:50:06+00","2041-10-21 23:59:59+00",1,"1",NULL,"123872.36","2026-04-23 10:31:45.186653+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082900168","KDD 913G_Ruth Mazda",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-23 15:09:48.575568+00","2026-04-23 15:09:48.575568+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"359857082900341","Simon Munda - KCZ 154S","GT06E","aotomobile","KCZ 154S","KCZ 154S","Probox","automobile",NULL,NULL,NULL,NULL,"Simon Munda",NULL,"757236135","89254021154296723312","639021159672331","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-09-23 17:12:51+00","2040-09-23 23:59:59+00",1,"1",NULL,"186504.10","2026-04-23 10:45:21.454595+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082900358","Geoffrey Too - KDM 308S","GT06E","aotomobile","KDM 308S","KDM 308S","Probox","automobile",NULL,NULL,NULL,NULL,"Geoffrey Too",NULL,"796527601","89254021264260126572","639021266012657","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-10-21 15:25:28+00","2041-10-21 23:59:59+00",1,"1",NULL,"142216.91","2026-04-23 12:35:06.661934+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082900697","George Ochieng' - KDD 684Y","GT06E","aotomobile","KDD 684Y","KDD 684Y","Probox","automobile",NULL,NULL,NULL,NULL,"George Ochieng'",NULL,"114879518","89254021214211314678","639021211131467","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-09-17 10:53:11+00","2041-09-17 23:59:59+00",1,"1",NULL,"152820.07","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082902461","Sadique Wakayula - KDC 490Q","GT06E","aotomobile","KDC 490Q","KDC 490Q","Crane","truck",NULL,NULL,NULL,NULL,"Sadique Wakayula",NULL,"757556468","89254021154296722488","639021159672248","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-05-22 11:27:30+00","2041-05-22 11:27:30+00",1,"1",NULL,"183009.52","2026-04-23 11:16:03.730519+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082902503","Felix Andole - KDC 207R","GT06E","aotomobile","KDC 207R","KDC 207R","Probox","automobile",NULL,NULL,NULL,NULL,"Felix Andole",NULL,"794820817","89254021224270993254","639021227099325","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-05-15 11:38:24+00","2041-05-15 11:38:24+00",1,"1",NULL,"208724.46","2026-04-23 15:32:46.935568+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082907973","Felix Muema - KCZ 223P","GT06E","aotomobile","KCZ 223P","KCZ 223P","Probox","automobile",NULL,NULL,NULL,NULL,"Felix Muema",NULL,"757843826","89254021154287138371","639021158713837","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-08-22 14:01:25+00","2040-08-22 23:59:59+00",1,"1",NULL,"222126.36","2026-04-23 10:26:48.220151+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082908500","Santoes Omondi - KCZ 181P","GT06E","aotomobile","KCZ 181P","KCZ 181P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Santoes Omondi",NULL,"701211974","89254021374215155087","639021371515508","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-08-23 08:58:55+00","2040-08-23 23:59:59+00",1,"1",NULL,"221339.62","2026-04-23 10:48:09.537346+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082910589","Patric Bett - KDA 609E","GT06E","aotomobile","KDA 609E","KDA 609E","Probox","automobile",NULL,NULL,NULL,NULL,"Patric Bett",NULL,"797622637","89254021154296722496","639021159672249","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2020-10-26 15:46:41+00","2040-10-26 23:59:59+00",1,"1",NULL,"194618.69","2026-04-23 10:34:25.350862+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082910886","Makanda Andrew - KCZ 155P","GT06E","aotomobile","KCZ 155P","KCZ 155P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Makanda Andrew",NULL,"745067338","89254021154287138397","639021158713839","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-08-23 11:52:35+00","2040-08-23 23:59:59+00",1,"1",NULL,"231065.89","2026-04-23 11:36:31.150282+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082911983","Brian Ngetich - KDA 717B","GT06E","aotomobile","KDA 717B","KDA 717B","Probox","automobile",NULL,NULL,NULL,NULL,"Brian Ngetich","795188807","795188807","89254021214211145288","639021211114528","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-08-29 07:21:43+00","2041-08-29 07:21:43+00",1,"1",NULL,"145404.96","2026-04-23 10:36:11.774166+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082912239","Dickson Jaoko - KDK 815R","GT06E","aotomobile","KDK 815R","KDK 815R","Probox","automobile",NULL,NULL,"Probox","0.00","Sammy",NULL,"706392117","89254021234296021287","639021239602128","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-06-21 07:14:51+00","2033-06-21 23:59:59+00",1,"1",NULL,"77008.75","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082912486","Moses Wambua - KCZ 751V","GT06E","aotomobile","KCZ 751V","KCZ 751V","Probox","automobile",NULL,NULL,NULL,NULL,"Moses Wambua","0792756503","792756503","89254021154296723437","639021159672343","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-09-23 10:14:28+00","2040-09-23 23:59:59+00",1,"1",NULL,"139762.20","2026-04-23 10:41:00.207177+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082916826","Denis Kazungu - KDM 794R","GT06E","aotomobile","KDM 794R","KDM 794R","Probox","automobile",NULL,NULL,NULL,NULL,"Denis Kazungu",NULL,"705700971","89254021324273006854","639021327300685","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2023-08-21 06:38:00+00","2033-08-21 23:59:59+00",1,"1",NULL,"79639.71","2026-04-23 20:18:46.496567+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082918012","Charles Nyambane - KCB 711C","GT06E","aotomobile","KCB 711C","KCB 711C","Probox","automobile",NULL,NULL,NULL,NULL,"Charles Nyambane",NULL,"793704231","89254021154287138363","639021158713836","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2020-09-21 10:48:35+00","2040-09-21 23:59:59+00",1,"1",NULL,"159597.27","2026-04-23 10:25:52.843474+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082918038","Mbuvi Kioko - KCC 199P","GT06E","aotomobile","KCC 199P","KCC 199P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Mbuvi Kioko",NULL,"797318126","89254021154287138389","639021158713838","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-08-22 15:26:27+00","2040-08-22 23:59:59+00",1,"1",NULL,"222106.80","2026-04-23 12:09:05.609075+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"359857082918186","KDD 977T Fielder",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-23 10:36:25.832836+00","2026-04-23 10:36:25.832836+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"359857082925330","Noel Merengeni - KCY 838X","GT06E","aotomobile","KCY 838X","KCY 838X","Probox","automobile",NULL,NULL,NULL,NULL,"Noel Merengeni",NULL,"794873610","89254021154296723429","639021159672342","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2020-10-26 16:36:37+00","2040-10-26 23:59:59+00",1,"1",NULL,"194429.24","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050288212","Nicholas Erastus - KCQ 581M","JC400P","aotomobile","KCQ 581M","KCQ 581M","Probox","automobile",NULL,NULL,NULL,NULL,"Nicholas Erastus",NULL,"746979531",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-11-02 09:07:41+00","2041-11-02 23:59:59+00",1,"1",NULL,"40898.98","2026-04-23 13:05:18.326254+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050288261","Patric Bett - KDA 609E","JC400P","aotomobile","KDA 609E","KDA 609E","Probox","automobile",NULL,NULL,NULL,NULL,"Patric Bett","112693340","790176509",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2021-10-23 11:50:11+00","2041-10-23 23:59:59+00",1,"1",NULL,"18538.42","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050288303","Elias Baya - KCZ 476E","JC400P","aotomobile","KCZ 476E","KCZ 476E","Probox","automobile",NULL,NULL,NULL,NULL,"Elias Baya",NULL,"115870439",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-11-06 08:50:28+00","2041-11-06 23:59:59+00",1,"1",NULL,"116091.42","2026-04-23 17:46:09.993791+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050288345","Santoes Omondi - KCZ 181P","JC400P","aotomobile","KCZ 181P","KCZ 181P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Santoes Omondi",NULL,"768446105",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2021-11-06 10:17:51+00","2041-11-06 23:59:59+00",1,"1",NULL,"107462.79","2026-04-23 10:29:45.563231+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050288360","Brian Ngetich - KDA 717B","JC400P","aotomobile","KDA 717B","KDA 717B","Probox","automobile",NULL,NULL,NULL,NULL,"Brian Ngetich",NULL,"717867861",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2021-11-05 08:47:08+00","2041-11-05 23:59:59+00",1,"1",NULL,"17808.56","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050521521","John Kimeria - KDS 525D","JC400P","aotomobile","KDS 525D","KDS 525D","Crane","truck",NULL,NULL,NULL,NULL,"John Kimeria",NULL,"752958416",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-11-26 07:58:13+00","2033-11-26 23:59:59+00",1,"1",NULL,"19354.92","2026-04-23 10:28:34.917147+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050521612","Denis Kazungu - KDM 794R","JC400P","aotomobile","KDM 794R","KDM 794R","Probox","automobile",NULL,NULL,NULL,NULL,"Denis Kazungu",NULL,"704113731",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-22 07:52:12+00","2042-01-22 23:59:59+00",1,"1",NULL,"4350.75","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050521752","Simon Munda - KCZ 154S","JC400P","aotomobile","KCZ 154S","KCZ 154S","Probox","automobile",NULL,NULL,NULL,NULL,"Simon Munda",NULL,"113805921",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 08:14:37+00","2042-01-16 23:59:59+00",1,"1",NULL,"4698.02","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522065","Gideon Kiprono - KCQ 215F","JC400P","aotomobile","KCQ 215F","KCQ 215F","Probox","automobile",NULL,NULL,NULL,NULL,"Gideon Kiprono",NULL,"113343715",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2022-01-16 07:10:16+00","2042-01-16 23:59:59+00",1,"1",NULL,"8111.98","2026-04-23 18:23:51.445608+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522107","Cassius Wakiyo - KDB 323M","JC400P","aotomobile","KDB 323M","KDB 323M","Probox","automobile",NULL,NULL,NULL,NULL,"Cassius Wakiyo",NULL,"114149576",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 08:18:15+00","2042-01-22 23:59:59+00",1,"1",NULL,"23316.09","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522719","Mbuvi Kioko - KCZ 199P","JC400P","aotomobile","KCZ 199P","KCZ 199P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Mbuvi Kioko",NULL,"768218655",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 22:07:24+00","2042-01-16 23:59:59+00",1,"1",NULL,"16973.89","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522743","Charles Nyambane - KCB 711C","JC400P","aotomobile","KCB 711C","KCB 711C","Probox","automobile",NULL,NULL,NULL,NULL,"Charles Nyambane",NULL,"768657106",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-12-22 21:53:57+00","2033-12-22 23:59:59+00",1,"1",NULL,"12133.75","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522859","Garage - KCH 167M","JC400P","aotomobile","KCH 167M","KCH 167M","Probox","automobile",NULL,NULL,NULL,NULL,"Garage",NULL,"706740252",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 08:23:21+00","2042-01-15 23:59:59+00",1,"1",NULL,"6934.86","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522883","Dan Watila - KDE 638J","JC400P","aotomobile","KDE 638J","KDE 638J","Probox","automobile",NULL,NULL,NULL,NULL,"Dan Watila",NULL,"112615393",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 07:17:21+00","2042-01-15 23:59:59+00",1,"1",NULL,"14483.01","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050522891","Lawrence Kijogi - KCY 080X","JC400P","aotomobile","KCY 080X","KCY 080X","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Lawrence Kijogi",NULL,"113287191",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 10:51:30+00","2042-01-16 23:59:59+00",1,"1",NULL,"11585.33","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523014","Samuel Muriithy - KDR 594N","JC400P","aotomobile","KDR 594N","KDR 594N","Probox","automobile",NULL,NULL,NULL,NULL,"Samuel Muriithy",NULL,"790175423",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-21 15:54:32+00","2033-12-21 23:59:59+00",1,"1",NULL,"27275.43","2026-04-23 10:26:17.747928+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523063","Kelvin Wambugu - KDR 594N","JC400P","aotomobile","KDR 594N","KDR 594N","Probox","automobile",NULL,NULL,NULL,NULL,"Kelvin Wambugu",NULL,"701211876",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 19:24:51+00","2043-12-22 19:24:51+00",1,"1",NULL,"32698.94","2026-04-23 15:31:08.065856+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523139","Mike Wanaswa - KDT 724R","JC400P","aotomobile","KDT 724R","KDT 724R","Probox","automobile",NULL,NULL,NULL,NULL,"Mike Wanaswa",NULL,"790175045",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 22:28:09+00","2043-12-22 22:28:09+00",1,"1",NULL,"29559.82","2026-04-23 11:16:37.277518+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523204","Amani Kazungu - KCY 084X","JC400P","aotomobile","KCY 084X","KCY 084X","Probox","automobile",NULL,NULL,NULL,NULL,"Amani Kazungu",NULL,"707892547",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 06:18:20+00","2042-01-16 23:59:59+00",1,"1",NULL,"66955.70","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523295","Emmanuel Luseno - KDS 453 Y","JC400P","aotomobile","KDS 453 Y","KDS 453 Y","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Emmanuel Luseno",NULL,"700242474",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 14:39:50+00","2033-12-22 23:59:59+00",1,"1",NULL,"37098.35","2026-04-23 11:29:48.369147+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523337","Victor Kimutai - KDS 919Y","JC400P","aotomobile","KDS 919Y","KDS 919Y","Probox","automobile",NULL,NULL,NULL,NULL,"Victor Kimutai",NULL,"700242527",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 18:00:49+00","2043-12-22 18:00:49+00",1,"1",NULL,"50756.64","2026-04-23 10:27:13.522675+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523386","George Ochieng' - KDD 684Y","JC400P","aotomobile","KDD 684Y","KDD 684Y","Probox","automobile",NULL,NULL,NULL,NULL,"George Ochieng'",NULL,"785586834",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 06:36:08+00","2042-01-22 23:59:59+00",1,"1",NULL,"33979.83","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523527","Allan Owana - KDK 780K","JC400P","aotomobile","KDK 780K","KDK 780K","Probox","automobile",NULL,NULL,NULL,NULL,"Allan Owana",NULL,"792375024",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2022-12-03 10:43:41+00","2042-12-03 23:59:59+00",1,"1",NULL,"109564.95","2026-04-23 10:25:24.360765+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523618","Geoffrey Too - KDM 308S","JC400P","aotomobile","KDM 308S","KDM 308S","Probox","automobile",NULL,NULL,NULL,NULL,"Geoffrey Too",NULL,"701211625",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-08-15 15:42:32+00","2033-08-15 23:59:59+00",1,"1",NULL,"26496.50","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523626","Major Simiyu - KDS 949Y","JC400P","aotomobile","KDS 949Y","KDS 949Y","Probox","automobile",NULL,NULL,NULL,NULL,"Major Simiyu",NULL,"701211892",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 18:05:16+00","2033-12-22 23:59:59+00",1,"1",NULL,"37042.97","2026-04-23 10:51:18.245194+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523816","Job Ngare - KDM 309S","JC400P","aotomobile","KDM 309S","KDM 309S","Probox","automobile",NULL,NULL,NULL,NULL,"Job Ngare",NULL,"707936781",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-08-15 14:05:52+00","2033-08-15 23:59:59+00",1,"1",NULL,"54320.21","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050523949","Joseph Kabandi - KCY 076X","JC400P","aotomobile","KCY 076X","KCY 076X","Probox","automobile",NULL,NULL,NULL,NULL,"Joseph Kabandi",NULL,"113288492",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 05:52:54+00","2042-01-16 23:59:59+00",1,"1",NULL,"14427.50","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524012","Moses Wambua - KCZ 751V","JC400P","aotomobile","KCZ 751V","KCZ 751V","Probox","automobile",NULL,NULL,NULL,NULL,"Moses Wambua",NULL,"113313797",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 07:40:10+00","2042-01-16 23:59:59+00",1,"1",NULL,"26551.46","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524087","Felix Muema - KCZ 223P","JC400P","aotomobile","KCZ 223P","KCZ 223P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Felix Muema",NULL,"113973875",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 13:02:24+00","2042-01-16 23:59:59+00",1,"1",NULL,"11543.26","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524368","862798050524368","JC400P","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-10-29 09:24:53+00","2042-10-29 23:59:59+00",1,"1",NULL,"169208.91","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524384","Hamisi Pande - KDD 689Y","JC400P","aotomobile","KDD 689Y","KDD 689Y","Probox","automobile",NULL,NULL,NULL,"0.00","Hamisi Pande",NULL,"701211744",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 05:49:19+00","2042-01-22 23:59:59+00",1,"1",NULL,"13685.18","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524392","Ndegwa Dancun - KCG 669W","JC400P","aotomobile","KCG 669W","KCG 669W","Probox","automobile",NULL,NULL,NULL,NULL,"Ndegwa Dancun",NULL,"113799173",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 09:43:10+00","2042-01-16 23:59:59+00",1,"1",NULL,"13638.25","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524426","Amani Sulubu - KCY 090X","JC400P","aotomobile","KCY 090X","KCY 090X","Probox","automobile",NULL,NULL,NULL,NULL,"Amani Sulubu",NULL,"113823350",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2022-01-16 08:56:25+00","2042-01-16 23:59:59+00",1,"1",NULL,"14243.83","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524533","Leonard Nzai - KDM 306S","JC400P","aotomobile","KDM 306S","KDM 306S","Probox","automobile",NULL,NULL,NULL,NULL,"Leonard Nzai",NULL,"703487162",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-08-21 08:22:12+00","2033-08-21 23:59:59+00",1,"1",NULL,"68942.41","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524558","Mutuku Joseph - KDC 739F","JC400P","aotomobile","KDC 739F","KDC 739F","Probox","automobile",NULL,NULL,NULL,NULL,"Mutuku Joseph",NULL,"100858817",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 10:38:25+00","2042-01-22 23:59:59+00",1,"1",NULL,"23711.63","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524566","Makanda Andrew - KCZ 155P","JC400P","aotomobile","KCZ 155P","KCZ 155P","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Makanda Andrew",NULL,"758781444",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-22 09:47:33+00","2042-01-22 23:59:59+00",1,"1",NULL,"31663.30","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524608","Peter Mbugua - KDK 728K","JC400P","aotomobile","KDK 728K","KDK 728K","Probox","automobile",NULL,NULL,NULL,NULL,"Peter Mbugua",NULL,"706742413",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-12-03 12:11:32+00","2042-12-03 23:59:59+00",1,"1",NULL,"7219.31","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524657","Felix Andole - KDC 207R","JC400P","aotomobile","KDC 207R","KDC 207R","Probox","automobile",NULL,NULL,NULL,NULL,"Felix Andole",NULL,"758689195",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 07:17:47+00","2042-01-22 23:59:59+00",1,"1",NULL,"46233.99","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524681","Mutuku Antony - KDK 732K","JC400P","aotomobile","KDK 732K","KDK 732K","Probox","automobile",NULL,NULL,NULL,NULL,"Mutuku Antony",NULL,"796275746",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-12-06 13:37:49+00","2042-12-06 23:59:59+00",1,"1",NULL,"14993.36","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524707","Garage - KCE 699F","JC400P","aotomobile","KCE 699F","KCE 699F","Probox","automobile",NULL,NULL,NULL,NULL,"Garage",NULL,"110525751",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 07:58:49+00","2042-01-15 23:59:59+00",1,"1",NULL,"34715.97","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050524897","Cornelius Kimutai - KCU 938R","JC400P","aotomobile","KCU 938R","KCU 938R","Van","automobile",NULL,NULL,NULL,NULL,"Cornelius Kimutai",NULL,"114924404",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-22 09:03:40+00","2042-01-22 23:59:59+00",1,"1",NULL,"12668.43","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525068","Samuel Ng'ang'a - KDE 264M","JC400P","aotomobile","KDE 264M","KDE 264M","Probox","automobile",NULL,NULL,NULL,NULL,"Samuel Ng'ang'a",NULL,"768658564",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-12-22 13:33:42+00","2033-12-22 23:59:59+00",1,"1",NULL,"12299.13","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525225","Sadique Wakayula - KDC 490Q","JC400P","aotomobile","KDC 490Q","KDC 490Q","Crane","truck",NULL,NULL,NULL,NULL,"Sadique Wakayula",NULL,"768652386",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-12-22 20:52:08+00","2043-12-22 20:52:08+00",1,"1",NULL,"19138.05","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525266","Dickson Jaoko - KDK 815R","JC400P","aotomobile","KDK 815R","KDK 815R","Probox","automobile",NULL,NULL,NULL,NULL,"Dickson Jaoko",NULL,"706665867",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-06-21 07:50:00+00","2033-06-21 23:59:59+00",1,"1",NULL,"63754.71","2026-04-23 13:50:24.21992+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525423","Makori John - KDB 585E","JC400P","aotomobile","KDB 585E","KDB 585E","Probox","automobile",NULL,NULL,NULL,NULL,"Makori John",NULL,"701211724",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 10:59:19+00","2042-01-15 23:59:59+00",1,"1",NULL,"48804.83","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525589","Simon Kamau - KCE 090R","JC400P","aotomobile","KCE 090R","KCE 090R","Probox","automobile",NULL,NULL,NULL,NULL,"Simon Kamau",NULL,"796276387",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-19 10:10:04+00","2042-01-19 23:59:59+00",1,"1",NULL,"15874.39","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525605","John Ondego - KCA 542Q","JC400P","aotomobile","KCA 542Q","KCA 542Q","Probox","automobile",NULL,NULL,NULL,NULL,"John Ondego",NULL,"110526783",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 05:56:11+00","2042-01-15 23:59:59+00",1,"1",NULL,"23976.94","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525613","Kennedy Chege - KCQ 618K","JC400P","aotomobile","KCQ 618K","KCQ 618K","Probox","automobile",NULL,NULL,NULL,NULL,"Kennedy Chege",NULL,"729994247",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-16 05:21:05+00","2042-01-16 23:59:59+00",1,"1",NULL,"12804.24","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525670","Gabriel Musumba - KCE 690F","JC400P","aotomobile","KCE 690F","KCE 690F","Probox","automobile",NULL,NULL,NULL,NULL,"Gabriel Musumba",NULL,"701211996",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2022-01-15 06:40:01+00","2042-01-15 23:59:59+00",1,"1",NULL,"20110.93","2026-04-24 05:34:23.167312+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525753","Noel Merengeni - KCY 838X","JC400P","aotomobile","KCY 838X","KCY 838X","Probox","automobile",NULL,NULL,NULL,NULL,"Noel Merengeni",NULL,NULL,NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2022-01-15 05:24:00+00","2042-01-15 23:59:59+00",1,"1",NULL,"14596.59","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525837","Kennedy Ondieki - KCU 237Z","JC400P","aotomobile","KCU 237Z","KCU 237Z","Probox","automobile",NULL,NULL,NULL,NULL,"Kennedy Ondieki",NULL,"113669852",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2023-12-21 19:32:44+00","2033-12-21 23:59:59+00",1,"1",NULL,NULL,"2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050525951","Wright Oseko - KCG 668W","JC400P","aotomobile","KCG 668W","KCG 668W","Probox","automobile",NULL,NULL,NULL,NULL,"Wright Oseko",NULL,"741943212",NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2022-01-15 09:36:45+00","2042-01-15 23:59:59+00",1,"1",NULL,"13116.00","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050526165","Wilfred Kinyanjui - KCU 729C","JC400P","aotomobile","KCU 729C","KCU 729C","Crane","truck",NULL,NULL,NULL,NULL,"Wilfred Kinyanjui",NULL,"790564929",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2023-11-26 10:17:19+00","2033-11-26 23:59:59+00",1,"1",NULL,"24270.20","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050526231","Rashid Hassan - KDM 840V","JC400P","aotomobile","KDM 840V","KDM 840V","Probox","automobile",NULL,NULL,NULL,NULL,"Rashid Hassan",NULL,"790175526",NULL,NULL,"Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2023-12-22 22:36:15+00","2043-12-22 22:36:15+00",1,"1",NULL,"45418.38","2026-04-23 10:29:41.575467+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798050526256","Ian Dancun - KDT 923R","JC400P","aotomobile","KDT 923R","KDT 923R","Probox","automobile",NULL,NULL,NULL,NULL,"Ian Dancun",NULL,"794873610",NULL,NULL,"Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2023-12-22 19:37:24+00","2043-12-22 19:37:24+00",1,"1",NULL,"11093.11","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052707888","Benjamin Ananda - KDV 438W","JC400P","aotomobile","KDV 438W","KDV 438W","Probox","automobile",NULL,NULL,NULL,NULL,"Benjamin Ananda",NULL,"758047312","89254021414206816980","639021410681698","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-12-15 07:39:23+00","2035-12-15 23:59:59+00",1,"1",NULL,"8720.87","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052707896","John Mbugua - KDW 573B","JC400P","aotomobile","KDW 573B","KDW 573B","Probox","automobile",NULL,NULL,NULL,NULL,"John Mbugua",NULL,NULL,"89254021414206816725","639021410681672","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-01-30 14:48:17+00","2036-01-30 23:59:59+00",1,"1",NULL,"515.16","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052707946","Tom Wekesa/OSP-KCY 930Y_CAM","JC400P","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,"0758047806","89254021414206816766","639021410681676","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2026-01-20 21:02:13+00","2036-01-20 23:59:59+00",1,"1",NULL,"10079.17","2026-04-23 10:25:24.363965+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052708035","862798052708035","JC400P","aotomobile",NULL,NULL,"Probox","automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,"fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group",NULL,NULL,1,"1",NULL,NULL,"2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052708068","Dominic Wambua - KDV 683Z","JC400P","aotomobile","KDV 683Z","KDV 683Z","Probox","automobile",NULL,NULL,NULL,NULL,"Dominic Wambua",NULL,"758048043","89254021414206816964","639021410681696","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-01-24 09:20:09+00","2036-01-24 23:59:59+00",1,"1",NULL,"4438.55","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052708076","Albert Mutwiri - KDV 437W","JC400P","aotomobile",NULL,"KDV 437W","Probox","automobile",NULL,NULL,NULL,NULL,"Albert Mutwiri",NULL,"758047094","89254021414206816782","639021410681678","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-12-13 15:03:30+00","2035-12-13 23:59:59+00",1,"1",NULL,"5575.64","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052708167","Levine Wasike - KDV 439W","JC400P","aotomobile","KDV 439W","KDV 439W","Probox","automobile",NULL,NULL,NULL,NULL,"Levine Wasike",NULL,"758046738","89254021414206816741","639021410681674","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-12-13 19:49:29+00","2035-12-13 23:59:59+00",1,"1",NULL,"4601.08","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052708282","Godffrey Nandwa - KCN 496A","JC400P","aotomobile","KCN 496A","KCN 496A","Probox","automobile",NULL,NULL,NULL,NULL,"Godffrey Nandwa",NULL,"758047934","89254021414206816865","639021410681686","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2026-01-25 18:55:54+00","2036-01-25 23:59:59+00",1,"1",NULL,"7040.60","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713654","Garage/ISP_KCL 502T_CAM","JC400P","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,"0780215879","89254035061001753803","639035060175380","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-09-02 10:09:57+00","2035-09-02 23:59:59+00",1,"1",NULL,"5199.72","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713696","862798052713696","JC400P","aotomobile",NULL,NULL,"Probox","automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"89254021394215205906","639021391520590","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-09-02 10:20:58+00","2035-09-02 23:59:59+00",1,"1",NULL,"6214.49","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713761","Management_Mazda - KDU 613A","JC400P","aotomobile","KDU 613A","KDU 613A","Mazda","automobile",NULL,NULL,NULL,NULL,"Management_Mazda",NULL,"790176786","89254021394215205955","639021391520595","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-07-09 15:49:26+00","2035-07-09 23:59:59+00",1,"1",NULL,"9262.78","2026-04-23 16:40:48.879666+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713779","Benard Kimutai - KDN 759G","JC400P","aotomobile","KDN 759G","KDN 759G","Probox","automobile",NULL,NULL,NULL,NULL,"Benard Kimutai",NULL,"752143258","89254035061001753860","639035060175386","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-08-23 11:15:59+00","2035-08-23 23:59:59+00",1,"1",NULL,"5344.24","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713811","James Onyango - KDU 613B","JC400P","aotomobile","KDU 613B","KDU 613B","Probox","automobile",NULL,NULL,NULL,NULL,"James Onyango",NULL,"790176542","89254021394215205880","639021391520588","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-09 19:24:14+00","2035-07-09 23:59:59+00",1,"1",NULL,"9657.42","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713837","Kennedy Ondieki - KCU 237Z","JC400P","aotomobile","KCU 237Z","KCU 237Z","Probox","automobile",NULL,NULL,NULL,NULL,"Kennedy Ondieki",NULL,"113669852","89254021414206327855","639021410632785","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-10-08 14:55:23+00","2035-10-08 23:59:59+00",1,"1",NULL,"9346.02","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052713985","Timothy Gitau - KDT 916R","JC400P","aotomobile","KDT 916R","KDT 916R","Probox","automobile",NULL,NULL,NULL,NULL,"Timothy Gitau",NULL,"768696668","89254021394274518892","639021397451889","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-08-02 18:21:23+00","2035-08-02 23:59:59+00",1,"1",NULL,"19998.22","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052714066","862798052714066","JC400P","aotomobile",NULL,NULL,"Probox","automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"89254021414206378684","639021410637868","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-11-21 17:44:44+00","2035-11-21 23:59:59+00",1,"1",NULL,"10755.28","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"862798052715220","Rofas Njagi - KDT 728R","JC400P","aotomobile","KDT 728R","KDT 728R","Probox","automobile",NULL,NULL,NULL,NULL,"Rofas Njagi",NULL,"704573658","89254021334258495873","639021335849587","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-16 07:09:25+00","2035-07-16 23:59:59+00",1,"1",NULL,"16385.58","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061035133","Major Simiyu - KDS 949Y","X3","aotomobile","KDS 949Y","KDS 949Y","Probox","automobile",NULL,NULL,NULL,NULL,"Major Simiyu",NULL,"768696642","89254021394274518918","639021397451891","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2025-08-02 13:14:33+00","2035-08-02 23:59:59+00",1,"1",NULL,"25089.98","2026-04-23 12:07:56.044395+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061035653","Richardson Komu - KDT 923R","X3","aotomobile","KDT 923R","KDT 923R","Probox","automobile",NULL,NULL,NULL,NULL,"Richardson Komu",NULL,"768697292","89254021394274518942","639021397451894","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-08-02 08:11:46+00","2035-08-02 23:59:59+00",1,"1",NULL,"23556.65","2026-04-23 10:24:50.340401+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061035778","John Kimeria - KDS 525D","X3","aotomobile","KDS 525D","KDS 525D","Crane","truck",NULL,NULL,NULL,NULL,"John Kimeria",NULL,"790176738","89254021394215205922","639021391520592","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-11 05:50:36+00","2035-07-11 23:59:59+00",1,"1",NULL,"17653.96","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061036164","Brian Njenga - KMFF 113Z","X3","aotomobile","KMFF 113Z","KMFF 113Z","Motorbike","mtc",NULL,NULL,NULL,NULL,"Brian Njenga",NULL,"768696705","89254021394274518850","639021397451885","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-31 10:06:46+00","2035-07-31 23:59:59+00",1,"1",NULL,"22990.33","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061037980","Emmanuel Luseno - KDS 453Y","X3","aotomobile","KDS 453Y","KDS 453Y","Pick-Up","automobile",NULL,NULL,NULL,NULL,"Emmanuel Luseno",NULL,"790176734","89254021394215205856","639021391520585","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-15 06:30:34+00","2035-07-15 23:59:59+00",1,"1",NULL,"42609.03","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061042261","Kelvin Wambugu - KDR 592N","X3","aotomobile","KDR 592N","KDR 592N","Probox","automobile",NULL,NULL,NULL,NULL,"Kelvin Wambugu",NULL,"797680464","89254021334258159693","639021335815969","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-10 10:23:44+00","2035-07-10 23:59:59+00",1,"1",NULL,"18755.66","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061043079","Mike Wanaswa - KDT 724R","X3","aotomobile","KDT 724R","KDT 724R","Probox","automobile",NULL,NULL,NULL,NULL,"Mike Wanaswa",NULL,"768696664","89254021394274518959","639021397451895","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2025-08-02 12:16:11+00","2035-08-02 23:59:59+00",1,"1",NULL,"27470.11","2026-04-23 11:16:35.682194+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061043426","Geoffrey Karanja - KMGS 239H","X3","aotomobile","KMGS 239H","KMGS 239H","Motorbike","mtc",NULL,NULL,NULL,NULL,"Geoffrey Karanja",NULL,"768696658","89254021394274518926","639021397451892","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-08-22 13:32:25+00","2035-08-22 23:59:59+00",1,"1",NULL,"21267.01","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061047435","Management_Mazda - KDU 613A","X3","aotomobile","KDU 613A","KDU 613A","Mazda","automobile",NULL,NULL,NULL,NULL,"Management_Mazda",NULL,"790175971","89254021394215205971","639021391520597","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-09 08:02:26+00","2035-07-09 23:59:59+00",1,"1",NULL,"9761.38","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061048276","Victor Kimutai - KDS 919Y","X3","aotomobile","KDS 919Y","KDS 919Y","Probox","automobile",NULL,NULL,NULL,NULL,"Victor Kimutai",NULL,"768696755","89254021394274518900","639021397451890","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2025-08-02 07:38:01+00","2035-08-02 23:59:59+00",1,"1",NULL,"23296.79","2026-04-23 10:54:41.63532+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061048300","KMGR 409U HENRY JAZZ",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-24 04:30:20.231102+00","2026-04-24 04:30:20.231102+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"865135061048466","Samuel Muriithy - KDR 594N","X3","aotomobile","KDR 594N","KDR 594N","Probox","automobile",NULL,NULL,NULL,NULL,"Samuel Muriithy",NULL,"797680395","89254021334258159628","639021335815962","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-07-24 09:37:31+00","2035-07-24 23:59:59+00",1,"1",NULL,"27634.10","2026-04-23 11:43:39.178819+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061048615","Office-KMDG 902Z","X3","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,"0768697276","89254021394274518876","639021397451887","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-31 09:59:43+00","2035-07-31 23:59:59+00",1,"1",NULL,"5721.21","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061048953","Timothy Gitau - KDT 916R","X3","aotomobile","KDT 916R","KDT 916R","Probox","automobile",NULL,NULL,NULL,NULL,"Timothy Gitau",NULL,"768697056","89254021394274518967","639021397451896","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2025-08-02 08:48:05+00","2035-08-02 23:59:59+00",1,"1",NULL,"28536.23","2026-04-23 10:53:31.102315+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061049001","Parked - KMGK 596V","X3","aotomobile","KMGK 596V","KMGK 596V","Motorbike","mtc",NULL,NULL,NULL,NULL,"Parked",NULL,"768697064","89254021394274518884","639021397451888","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-31 08:40:18+00","2035-07-31 23:59:59+00",1,"1",NULL,"20612.89","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061053714","Samuel Kihara - KMEL 225X","X3","aotomobile","KMEL 225X","KMEL 225X","Motorbike","mtc",NULL,NULL,NULL,NULL,"Samuel Kihara",NULL,"768696832","89254021394274518934","639021397451893","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-08-02 13:51:47+00","2035-08-02 23:59:59+00",1,"1",NULL,"26897.18","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061053748","Rashid Hassan - KDM 840V","X3","aotomobile","KDM 840V","KDM 840V","Probox","automobile",NULL,NULL,NULL,NULL,"Rashid Hassan",NULL,"768445963","89254021334212352574","639021331235257","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-07-10 13:54:11+00","2035-07-10 23:59:59+00",1,"1",NULL,"26612.42","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061054548","James Onyango - KDU 613B","X3","aotomobile","KDU 613B","KDU 613B","Probox","automobile",NULL,NULL,NULL,NULL,"James Onyango",NULL,"790175997","89254021394215205948","639021391520594","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-07-09 07:11:15+00","2035-07-09 23:59:59+00",1,"1",NULL,"13446.05","2026-04-23 10:26:24.667167+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061054555","Rofas Njagi - KDT 728R","X3","aotomobile","KDT 728R","KDT 728R","Probox","automobile",NULL,NULL,NULL,NULL,"Rofas Njagi",NULL,"790176726","89254021394215205823","639021391520582","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-07-16 06:44:33+00","2035-07-16 23:59:59+00",1,"1",NULL,"27250.80","2026-04-23 10:25:21.085437+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061559538","FRED KMGW 538W HULETI",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-23 10:42:18.5831+00","2026-04-23 10:42:18.5831+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"865135061562722","John Mbugua - KDW 573B","X3","aotomobile","KDW 573B","KDW 573B","Probox","automobile",NULL,NULL,NULL,NULL,"John Mbugua",NULL,"758052508","89254021414206816832","639021410681683","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2026-01-30 06:53:57+00","2036-01-30 23:59:59+00",1,"1",NULL,"4488.19","2026-04-23 10:25:38.887433+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061562847","Levine Wasike - KDV 439W","X3","aotomobile","KDV 439W","KDV 439W","Probox","automobile",NULL,NULL,NULL,NULL,"Levine Wasike",NULL,"758047032","89254021414206816840","639021410681684","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2025-12-13 11:14:14+00","2035-12-13 23:59:59+00",1,"1",NULL,"7880.92","2026-04-23 10:35:50.779597+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061563282","X3-63282","X3","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"8925610001837573427F","641101970467668","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-02-14 07:20:10+00","2036-02-14 23:59:59+00",1,"1",NULL,"4758.32","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061563415","Barack Orwa - KDW 781E","X3","aotomobile","KDW 781E","KDW 781E","Vazel","automobile",NULL,NULL,NULL,NULL,"Barack Orwa",NULL,"758052541","89254021414206816931","639021410681693","Fireside_MSA","Fireside Group MSA","9d0927d235e44fe7abf254902fc68921","Default group","2026-01-13 12:37:42+00","2036-01-13 23:59:59+00",1,"1",NULL,"4165.95","2026-04-23 11:22:00.676215+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061563423","Joel Ntumba - UMA 826AB","X3","aotomobile","UMA 826AB","UMA 826AB","Motorbike","mtc",NULL,NULL,NULL,NULL,"Joel Ntumba",NULL,"119051036","89254021414206652690","639021410665269","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-01-28 13:55:39+00","2036-01-28 23:59:59+00",1,"1",NULL,"1174.05","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061563597","Dominic Wambua - KDV 683Z","X3","aotomobile","KDV 683Z","KDV 683Z","Probox","automobile",NULL,NULL,NULL,NULL,"Dominic Wambua",NULL,"758052405","89254021414206816733","639021410681673","Fireside@HQ","Fireside Telematics","6ef0b0fc2d964b358b70dc2cfcbc5b7e","Default group","2026-01-30 06:55:35+00","2036-01-30 23:59:59+00",1,"1",NULL,"6790.53","2026-04-23 10:25:40.125927+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061563639","Benjamin Ananda - KDV 438W","X3","aotomobile","KDV 438W","KDV 438W","Probox","automobile",NULL,NULL,NULL,NULL,"Benjamin Ananda",NULL,"758047065","89254021414206816683","639021410681668","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-12-13 16:02:37+00","2035-12-13 23:59:59+00",1,"1",NULL,"14446.33","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061564280","Rodin Kiberu - UMA 011EK","X3","aotomobile","UMA 011EK","UMA 011EK","Motorbike","mtc",NULL,NULL,NULL,NULL,"Rodin Kiberu",NULL,"118081642","89254021414206817244","639021410681724","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-01-28 13:13:57+00","2036-01-28 23:59:59+00",1,"1",NULL,"841.39","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061564470","Silvanus Kipkorir - KDV 064S","X3","aotomobile","KDV 064S","KDV 064S","Probox","automobile",NULL,NULL,NULL,NULL,"Silvanus Kipkorir",NULL,"113669866","89254021414206378718","639021410637871","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-11-21 16:49:17+00","2035-11-21 23:59:59+00",1,"1",NULL,"23869.16","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061568968","X3-68968","X3","aotomobile",NULL,NULL,NULL,"automobile",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"89254021414206816915","639021410681691","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-03-11 06:19:14+00","2036-03-11 23:59:59+00",1,"1",NULL,"16.23","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061569123","Albert Mutwiri - KDV 437W","X3","aotomobile","KDV 437W","KDV 437W","Probox","automobile",NULL,NULL,NULL,NULL,"Albert Mutwiri",NULL,"758047101","89254021414206816881","639021410681688","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-12-13 14:26:17+00","2035-12-13 23:59:59+00",1,"1",NULL,"13032.60","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061569131","UMA 418EK","X3","aotomobile","UMA 418EK","UMA 418EK",NULL,"automobile",NULL,NULL,NULL,NULL,"UG",NULL,"256792997053","8925610001837573385F","641101970467664","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-02-26 08:15:44+00","2036-02-26 23:59:59+00",1,"1",NULL,"2333.45","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061569479","UMA 382EK","X3","aotomobile","UMA 382EK","UMA 382EK",NULL,"automobile",NULL,NULL,NULL,NULL,"UG",NULL,"256792997079","8925610001837573419F","641101970467667","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2026-02-26 08:21:10+00","2036-02-26 23:59:59+00",1,"1",NULL,"1954.86","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
"865135061578553","X3-78553",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,"unknown",NULL,NULL,"2026-04-23 15:30:19.981271+00","2026-04-23 15:30:19.981271+00",NULL,NULL,NULL,NULL,NULL,NULL,NULL
"865135061581904","Robert Kipruto - KDV 072L","X3","aotomobile","KDV 072L","KDV 072L","Probox","automobile",NULL,NULL,NULL,NULL,"Robert Kipruto",NULL,"114149576","89254021264261503993","639021266150399","fireside","Fireside Group HQ","2f1acaef6c884214b4598719180fe68d","Default group","2025-11-21 15:30:29+00","2035-11-21 23:59:59+00",1,"1",NULL,"15252.84","2026-04-23 10:23:56.546784+00","2026-04-24 07:43:45.210628+00","2026-04-24 07:43:45.210628+00",NULL,NULL,NULL,NULL,NULL,NULL
1 imei device_name mc_type mc_type_use_scope vehicle_name vehicle_number vehicle_models vehicle_icon vin engine_number vehicle_brand fuel_100km driver_name driver_phone sim iccid imsi account customer_name device_group_id device_group activation_time expiration enabled_flag status city current_mileage_km created_at updated_at last_synced_at vehicle_category cost_centre assigned_route depot_geom depot_address assigned_city
2 353549090553685 Daniel Omondi - KMFF 099Z AT4 personal KMFF 099Z KMFF 099Z Motorbike mtc NULL NULL NULL NULL Robert 0112794067 759336150 89254021334258404099 639021335840409 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 05:50:30+00 2040-09-23 23:59:59+00 1 1 NULL 2354.70 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
3 353549090561720 Wireless_Git AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0701211913 89254021374215155053 639021371515505 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-06-09 09:12:50+00 2035-06-09 23:59:59+00 1 1 NULL 5992.43 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
4 353549090566281 KDR 592N AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0797680464 89254021334258159693 639021335815969 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-11-08 04:01:30+00 2034-11-08 23:59:59+00 1 1 NULL 7771.90 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
5 353549090566885 Wireless GPS AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0768445963 89254021334212352574 639021331235257 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-10-15 13:16:57+00 2034-10-15 23:59:59+00 1 1 NULL 17036.41 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
6 353549090567685 Daniel Kipkirui - KMFF 162Z AT4 personal KMFF 162Z KMFF 162Z Motorbike mtc NULL NULL NULL NULL edwine 0112795498 742532058 89254021264260388966 639021266038896 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 05:09:39+00 2040-09-23 23:59:59+00 1 1 NULL 462.33 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
7 353549090567701 Wireless AT4 personal NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0790176094 89254021394215205906 639021391520590 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2024-11-08 04:04:44+00 2034-11-08 23:59:59+00 1 1 NULL 16896.20 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
8 359857081885410 Allan Owana - KDK 780K GT06E aotomobile KDK 780K KDK 780K Probox automobile NULL NULL NULL NULL Allan Owana NULL 703616117 89254021234222499854 639021232249985 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-19 09:32:22+00 2039-06-19 23:59:59+00 1 1 NULL 128853.11 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
9 359857081886467 Gideon Kiprono - KCQ 215F GT06E aotomobile KCQ 215F OHS Probox automobile NULL NULL NULL 0.00 Gideon Kiprono NULL 746763076 89254021084186499865 639021088649986 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-30 09:30:00+00 2039-06-30 23:59:59+00 1 1 NULL 141057.46 2026-04-23 10:56:37.983314+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
10 359857081886871 Kamonde KBA 467S GT06E aotomobile NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0746763083 89254021084186499873 639021088649987 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-30 09:09:14+00 2039-06-30 23:59:59+00 1 1 NULL 74183.36 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
11 359857081886905 Kennedy Chege - KCQ 618K GT06E aotomobile KCQ 618K KCQ 618K Probox automobile NULL NULL NULL NULL Kennedy Chege NULL 746763132 89254021084186499923 639021088649992 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-30 07:08:35+00 2039-06-30 23:59:59+00 1 1 NULL 215608.19 2026-04-23 10:35:37.678371+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
12 359857081887069 Wright Oseko - KCG 668W GT06E aotomobile KCG 668W KCG 668W Probox automobile NULL NULL NULL NULL Wright Oseko NULL 746763106 89254021084186499915 639021088649991 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-30 06:17:43+00 2039-06-30 23:59:59+00 1 1 NULL 239001.19 2026-04-23 11:00:08.769463+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
13 359857081887192 Ndegwa Dancun - KCG 669W GT06E aotomobile KCG 669W KCG 669W Probox automobile NULL NULL NULL NULL Ndegwa Dancun NULL 746760191 89254021084186499501 639021088649950 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2019-06-15 10:26:15+00 2039-06-15 23:59:59+00 1 1 NULL 199191.85 2026-04-23 10:34:29.074112+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
14 359857081891566 Simon Kamau - KCE 090R GT06E aotomobile KCE 090R KCE 090R Probox automobile NULL NULL NULL NULL Simon Kamau NULL 746760404 89254021084186499527 639021088649952 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-16 07:06:15+00 2039-06-16 23:59:59+00 1 1 NULL 215592.36 2026-04-23 10:30:55.739184+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
15 359857081891590 Garage - KCE 699F GT06E aotomobile KCE 699F KCE 699F Probox automobile NULL NULL NULL NULL Garage NULL 746760215 89254021084186499519 639021088649951 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-16 11:11:24+00 2039-06-16 23:59:59+00 1 1 NULL 207814.05 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
16 359857081891632 John Ondego - KCA 542Q GT06E aotomobile KCA 542Q KCA 542Q Probox automobile NULL NULL NULL NULL John Ondego NULL 746760038 89254021084186499485 639021088649948 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-15 09:17:53+00 2039-06-15 23:59:59+00 1 1 NULL 178914.47 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
17 359857081891798 Garage - KCH 167M GT06E aotomobile KCH 167M KCH 167M Probox automobile NULL NULL NULL NULL Garage NULL 746760102 89254021084186499493 639021088649949 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-16 10:18:57+00 2039-06-16 23:59:59+00 1 1 NULL 168840.95 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
18 359857081892101 Cornelius Kimutai - KCU 938R GT06E aotomobile KCU 938R KCU 938R Van automobile NULL NULL NULL NULL Cornelius Kimutai NULL 746759919 89254021084186499451 639021088649945 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-12 08:13:48+00 2039-06-12 23:59:59+00 1 1 NULL 149558.50 2026-04-23 10:29:21.507861+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
19 359857081892309 Nicholas Erastus - KCQ 581M GT06E aotomobile KCQ 581M KCQ 581M Probox automobile NULL NULL NULL NULL Nicholas Erastus NULL 700023776 89254021084178504672 639021087850467 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2019-06-09 09:39:40+00 2039-06-09 23:59:59+00 1 1 NULL 209105.89 2026-04-23 10:40:40.169684+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
20 359857081892440 KAZ 489Z GT06E aotomobile NULL NULL NULL bus NULL NULL NULL NULL NULL NULL 0700023806 89254021084178504698 639021087850469 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-09 10:04:39+00 2039-06-09 23:59:59+00 1 1 NULL 38197.20 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
21 359857081892762 Nicholas GT06E aotomobile NULL NULL Station Wagon bus NULL NULL Toyota NULL NULL NULL 0746760503 89254021274233125361 639021273312536 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2019-06-16 08:31:46+00 2039-06-16 23:59:59+00 1 1 NULL 51048.97 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
22 359857082037185 Amani Kazungu - KCY 084X GT06E aotomobile KCY 084X KCY 084X Probox automobile NULL NULL NULL NULL Amani Kazungu NULL 757338522 89254021154287000597 639021158700059 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 09:42:28+00 2040-07-13 23:59:59+00 1 1 NULL 172298.81 2026-04-23 10:51:08.665273+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
23 359857082038977 Wilfred Kinyanjui - KCU 729C GT06E aotomobile KCU 729C KCU 729C Crane truck NULL NULL NULL NULL Wilfred Kinyanjui NULL 110094469 89254021164215938057 639021161593805 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-04-05 09:26:00+00 2040-04-05 23:59:59+00 1 1 NULL 172487.09 2026-04-23 10:24:33.914628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
24 359857082040981 Amani Sulubu - KCY 090X GT06E aotomobile KCY 090X KCY 090X Probox automobile NULL NULL NULL NULL Amani Sulubu NULL 793375853 89254021064168004164 639021066800416 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 07:25:16+00 2040-07-13 23:59:59+00 1 1 NULL 166028.15 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
25 359857082042052 Gabriel Musumba - KCE 690F GT06E aotomobile KCE 690F KCE 690F Probox automobile NULL NULL NULL NULL Gabriel Musumba NULL 110094466 89254021164215938024 639021161593802 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2020-04-03 17:30:13+00 2040-04-03 23:59:59+00 1 1 NULL 192693.23 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
26 359857082042854 Elias Baya - KCZ 476E GT06E aotomobile KCZ 476E KCZ 476E Probox automobile NULL NULL NULL NULL Elias Baya NULL 110941187 89254021164224352993 639021162435299 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-09 05:06:42+00 2040-08-09 23:59:59+00 1 1 NULL 217595.68 2026-04-23 10:33:56.216621+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
27 359857082042953 KCU 865Q Vanguard NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-23 13:24:33.293453+00 2026-04-23 13:24:33.293453+00 NULL NULL NULL NULL NULL NULL NULL
28 359857082044280 Lawrence Kijogi - KCY 080X GT06E aotomobile KCY 080X KCY 080X Probox automobile NULL NULL NULL NULL Lawrence Kijogi NULL 708155933 89254029851005131222 639029850513122 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 11:05:02+00 2040-07-13 11:05:02+00 1 1 NULL 169740.37 2026-04-23 14:52:58.983571+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
29 359857082046145 Joseph Kabandi - KCY 076X GT06E aotomobile KCY 076X KCY 076X Probox automobile NULL NULL NULL NULL Joseph Kabandi NULL 110850007 89254021164223447158 639021162344715 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-07-13 08:31:26+00 2040-07-13 23:59:59+00 1 1 NULL 122254.48 2026-04-23 10:47:40.895504+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
30 359857082896911 Hamisi Pande - KDD 689Y GT06E aotomobile KDD 689Y KDD 689Y Probox automobile NULL NULL NULL NULL Hamisi Pande NULL 112714612 89254021214211314660 639021211131466 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-09-17 11:50:53+00 2041-09-17 23:59:59+00 1 1 NULL 163435.74 2026-04-23 10:26:09.922447+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
31 359857082897091 Peter Mbugua - KDK 728K GT06E aotomobile KDK 728K KDK 728K Probox automobile NULL NULL NULL NULL Peter Mbugua NULL 790262984 89254021234222500396 639021232250039 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-12-14 11:31:57+00 2042-12-14 23:59:59+00 1 1 NULL 131109.26 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
32 359857082897257 Cassius Wakiyo - KDB 323M GT06E aotomobile KDB 323M KDB 323M Probox automobile NULL NULL NULL NULL Cassius Wakiyo NULL 746428882 89254021234222500818 639021232250081 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 15:07:26+00 2041-08-29 15:07:26+00 1 1 NULL 121688.92 2026-04-23 10:28:26.388654+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
33 359857082897737 John Makori - KDB 585E GT06E aotomobile KDB 585E KDB 585E Probox automobile NULL NULL NULL NULL John Makori NULL 114596734 89254021214211145262 639021211114526 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 14:29:28+00 2041-08-29 14:29:28+00 1 1 NULL 156765.03 2026-04-23 10:38:57.445964+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
34 359857082897794 Mutuku Joseph - KDC 739F GT06E aotomobile KDC 739F KDC 739F Probox automobile NULL NULL NULL NULL Mutuku Joseph 115019037 115019037 89254021224222632356 639021222263235 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-04-10 14:55:32+00 2041-04-10 14:55:32+00 1 1 NULL 205169.79 2026-04-23 10:30:22.530563+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
35 359857082898008 Samuel Ng'ang'a - KDE 264M GT06E aotomobile KDE 264M KDE 264M Probox automobile NULL NULL NULL NULL Samuel Ng'ang'a NULL 711731539 89254021264260342245 639021266034224 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-28 09:43:11+00 2041-10-28 23:59:59+00 1 1 NULL 126584.24 2026-04-23 11:35:59.816581+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
36 359857082898016 Job Ngare - KDM 309S GT06E aotomobile KDM 309S KDM 309S Probox automobile NULL NULL NULL NULL Job Ngare NULL 706895756 89254021324273007563 639021327300756 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-08-15 13:45:26+00 2033-08-15 23:59:59+00 1 1 NULL 107726.56 2026-04-23 11:20:25.939244+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
37 359857082898073 Mutuku Antony - KDK 732K GT06E aotomobile KDK 732K KDK 732K Probox automobile NULL NULL NULL NULL Mutuku Antony NULL 793026954 89254021234222387539 639021232238753 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-12-20 06:33:12+00 2042-12-20 23:59:59+00 1 1 NULL 82096.79 2026-04-23 14:52:07.094447+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
38 359857082898487 Dan Watila - KDE 638J GT06E aotomobile KDE 638J KDE 638J Probox automobile NULL NULL NULL NULL Dan Watila NULL 116242996 89254021334258404214 639021335840421 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-21 15:50:06+00 2041-10-21 23:59:59+00 1 1 NULL 123872.36 2026-04-23 10:31:45.186653+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
39 359857082900168 KDD 913G_Ruth Mazda NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-23 15:09:48.575568+00 2026-04-23 15:09:48.575568+00 NULL NULL NULL NULL NULL NULL NULL
40 359857082900341 Simon Munda - KCZ 154S GT06E aotomobile KCZ 154S KCZ 154S Probox automobile NULL NULL NULL NULL Simon Munda NULL 757236135 89254021154296723312 639021159672331 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 17:12:51+00 2040-09-23 23:59:59+00 1 1 NULL 186504.10 2026-04-23 10:45:21.454595+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
41 359857082900358 Geoffrey Too - KDM 308S GT06E aotomobile KDM 308S KDM 308S Probox automobile NULL NULL NULL NULL Geoffrey Too NULL 796527601 89254021264260126572 639021266012657 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-10-21 15:25:28+00 2041-10-21 23:59:59+00 1 1 NULL 142216.91 2026-04-23 12:35:06.661934+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
42 359857082900697 George Ochieng' - KDD 684Y GT06E aotomobile KDD 684Y KDD 684Y Probox automobile NULL NULL NULL NULL George Ochieng' NULL 114879518 89254021214211314678 639021211131467 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-09-17 10:53:11+00 2041-09-17 23:59:59+00 1 1 NULL 152820.07 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
43 359857082902461 Sadique Wakayula - KDC 490Q GT06E aotomobile KDC 490Q KDC 490Q Crane truck NULL NULL NULL NULL Sadique Wakayula NULL 757556468 89254021154296722488 639021159672248 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-05-22 11:27:30+00 2041-05-22 11:27:30+00 1 1 NULL 183009.52 2026-04-23 11:16:03.730519+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
44 359857082902503 Felix Andole - KDC 207R GT06E aotomobile KDC 207R KDC 207R Probox automobile NULL NULL NULL NULL Felix Andole NULL 794820817 89254021224270993254 639021227099325 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-05-15 11:38:24+00 2041-05-15 11:38:24+00 1 1 NULL 208724.46 2026-04-23 15:32:46.935568+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
45 359857082907973 Felix Muema - KCZ 223P GT06E aotomobile KCZ 223P KCZ 223P Probox automobile NULL NULL NULL NULL Felix Muema NULL 757843826 89254021154287138371 639021158713837 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-22 14:01:25+00 2040-08-22 23:59:59+00 1 1 NULL 222126.36 2026-04-23 10:26:48.220151+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
46 359857082908500 Santoes Omondi - KCZ 181P GT06E aotomobile KCZ 181P KCZ 181P Pick-Up automobile NULL NULL NULL NULL Santoes Omondi NULL 701211974 89254021374215155087 639021371515508 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-23 08:58:55+00 2040-08-23 23:59:59+00 1 1 NULL 221339.62 2026-04-23 10:48:09.537346+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
47 359857082910589 Patric Bett - KDA 609E GT06E aotomobile KDA 609E KDA 609E Probox automobile NULL NULL NULL NULL Patric Bett NULL 797622637 89254021154296722496 639021159672249 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2020-10-26 15:46:41+00 2040-10-26 23:59:59+00 1 1 NULL 194618.69 2026-04-23 10:34:25.350862+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
48 359857082910886 Makanda Andrew - KCZ 155P GT06E aotomobile KCZ 155P KCZ 155P Pick-Up automobile NULL NULL NULL NULL Makanda Andrew NULL 745067338 89254021154287138397 639021158713839 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-23 11:52:35+00 2040-08-23 23:59:59+00 1 1 NULL 231065.89 2026-04-23 11:36:31.150282+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
49 359857082911983 Brian Ngetich - KDA 717B GT06E aotomobile KDA 717B KDA 717B Probox automobile NULL NULL NULL NULL Brian Ngetich 795188807 795188807 89254021214211145288 639021211114528 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-08-29 07:21:43+00 2041-08-29 07:21:43+00 1 1 NULL 145404.96 2026-04-23 10:36:11.774166+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
50 359857082912239 Dickson Jaoko - KDK 815R GT06E aotomobile KDK 815R KDK 815R Probox automobile NULL NULL Probox 0.00 Sammy NULL 706392117 89254021234296021287 639021239602128 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-06-21 07:14:51+00 2033-06-21 23:59:59+00 1 1 NULL 77008.75 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
51 359857082912486 Moses Wambua - KCZ 751V GT06E aotomobile KCZ 751V KCZ 751V Probox automobile NULL NULL NULL NULL Moses Wambua 0792756503 792756503 89254021154296723437 639021159672343 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-09-23 10:14:28+00 2040-09-23 23:59:59+00 1 1 NULL 139762.20 2026-04-23 10:41:00.207177+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
52 359857082916826 Denis Kazungu - KDM 794R GT06E aotomobile KDM 794R KDM 794R Probox automobile NULL NULL NULL NULL Denis Kazungu NULL 705700971 89254021324273006854 639021327300685 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-08-21 06:38:00+00 2033-08-21 23:59:59+00 1 1 NULL 79639.71 2026-04-23 20:18:46.496567+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
53 359857082918012 Charles Nyambane - KCB 711C GT06E aotomobile KCB 711C KCB 711C Probox automobile NULL NULL NULL NULL Charles Nyambane NULL 793704231 89254021154287138363 639021158713836 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2020-09-21 10:48:35+00 2040-09-21 23:59:59+00 1 1 NULL 159597.27 2026-04-23 10:25:52.843474+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
54 359857082918038 Mbuvi Kioko - KCC 199P GT06E aotomobile KCC 199P KCC 199P Pick-Up automobile NULL NULL NULL NULL Mbuvi Kioko NULL 797318126 89254021154287138389 639021158713838 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-08-22 15:26:27+00 2040-08-22 23:59:59+00 1 1 NULL 222106.80 2026-04-23 12:09:05.609075+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
55 359857082918186 KDD 977T Fielder NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-23 10:36:25.832836+00 2026-04-23 10:36:25.832836+00 NULL NULL NULL NULL NULL NULL NULL
56 359857082925330 Noel Merengeni - KCY 838X GT06E aotomobile KCY 838X KCY 838X Probox automobile NULL NULL NULL NULL Noel Merengeni NULL 794873610 89254021154296723429 639021159672342 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2020-10-26 16:36:37+00 2040-10-26 23:59:59+00 1 1 NULL 194429.24 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
57 862798050288212 Nicholas Erastus - KCQ 581M JC400P aotomobile KCQ 581M KCQ 581M Probox automobile NULL NULL NULL NULL Nicholas Erastus NULL 746979531 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-02 09:07:41+00 2041-11-02 23:59:59+00 1 1 NULL 40898.98 2026-04-23 13:05:18.326254+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
58 862798050288261 Patric Bett - KDA 609E JC400P aotomobile KDA 609E KDA 609E Probox automobile NULL NULL NULL NULL Patric Bett 112693340 790176509 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2021-10-23 11:50:11+00 2041-10-23 23:59:59+00 1 1 NULL 18538.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
59 862798050288303 Elias Baya - KCZ 476E JC400P aotomobile KCZ 476E KCZ 476E Probox automobile NULL NULL NULL NULL Elias Baya NULL 115870439 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-06 08:50:28+00 2041-11-06 23:59:59+00 1 1 NULL 116091.42 2026-04-23 17:46:09.993791+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
60 862798050288345 Santoes Omondi - KCZ 181P JC400P aotomobile KCZ 181P KCZ 181P Pick-Up automobile NULL NULL NULL NULL Santoes Omondi NULL 768446105 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2021-11-06 10:17:51+00 2041-11-06 23:59:59+00 1 1 NULL 107462.79 2026-04-23 10:29:45.563231+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
61 862798050288360 Brian Ngetich - KDA 717B JC400P aotomobile KDA 717B KDA 717B Probox automobile NULL NULL NULL NULL Brian Ngetich NULL 717867861 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2021-11-05 08:47:08+00 2041-11-05 23:59:59+00 1 1 NULL 17808.56 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
62 862798050521521 John Kimeria - KDS 525D JC400P aotomobile KDS 525D KDS 525D Crane truck NULL NULL NULL NULL John Kimeria NULL 752958416 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-11-26 07:58:13+00 2033-11-26 23:59:59+00 1 1 NULL 19354.92 2026-04-23 10:28:34.917147+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
63 862798050521612 Denis Kazungu - KDM 794R JC400P aotomobile KDM 794R KDM 794R Probox automobile NULL NULL NULL NULL Denis Kazungu NULL 704113731 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-22 07:52:12+00 2042-01-22 23:59:59+00 1 1 NULL 4350.75 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
64 862798050521752 Simon Munda - KCZ 154S JC400P aotomobile KCZ 154S KCZ 154S Probox automobile NULL NULL NULL NULL Simon Munda NULL 113805921 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 08:14:37+00 2042-01-16 23:59:59+00 1 1 NULL 4698.02 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
65 862798050522065 Gideon Kiprono - KCQ 215F JC400P aotomobile KCQ 215F KCQ 215F Probox automobile NULL NULL NULL NULL Gideon Kiprono NULL 113343715 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-16 07:10:16+00 2042-01-16 23:59:59+00 1 1 NULL 8111.98 2026-04-23 18:23:51.445608+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
66 862798050522107 Cassius Wakiyo - KDB 323M JC400P aotomobile KDB 323M KDB 323M Probox automobile NULL NULL NULL NULL Cassius Wakiyo NULL 114149576 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 08:18:15+00 2042-01-22 23:59:59+00 1 1 NULL 23316.09 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
67 862798050522719 Mbuvi Kioko - KCZ 199P JC400P aotomobile KCZ 199P KCZ 199P Pick-Up automobile NULL NULL NULL NULL Mbuvi Kioko NULL 768218655 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 22:07:24+00 2042-01-16 23:59:59+00 1 1 NULL 16973.89 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
68 862798050522743 Charles Nyambane - KCB 711C JC400P aotomobile KCB 711C KCB 711C Probox automobile NULL NULL NULL NULL Charles Nyambane NULL 768657106 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 21:53:57+00 2033-12-22 23:59:59+00 1 1 NULL 12133.75 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
69 862798050522859 Garage - KCH 167M JC400P aotomobile KCH 167M KCH 167M Probox automobile NULL NULL NULL NULL Garage NULL 706740252 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 08:23:21+00 2042-01-15 23:59:59+00 1 1 NULL 6934.86 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
70 862798050522883 Dan Watila - KDE 638J JC400P aotomobile KDE 638J KDE 638J Probox automobile NULL NULL NULL NULL Dan Watila NULL 112615393 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 07:17:21+00 2042-01-15 23:59:59+00 1 1 NULL 14483.01 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
71 862798050522891 Lawrence Kijogi - KCY 080X JC400P aotomobile KCY 080X KCY 080X Pick-Up automobile NULL NULL NULL NULL Lawrence Kijogi NULL 113287191 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 10:51:30+00 2042-01-16 23:59:59+00 1 1 NULL 11585.33 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
72 862798050523014 Samuel Muriithy - KDR 594N JC400P aotomobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Samuel Muriithy NULL 790175423 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-21 15:54:32+00 2033-12-21 23:59:59+00 1 1 NULL 27275.43 2026-04-23 10:26:17.747928+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
73 862798050523063 Kelvin Wambugu - KDR 594N JC400P aotomobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Kelvin Wambugu NULL 701211876 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 19:24:51+00 2043-12-22 19:24:51+00 1 1 NULL 32698.94 2026-04-23 15:31:08.065856+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
74 862798050523139 Mike Wanaswa - KDT 724R JC400P aotomobile KDT 724R KDT 724R Probox automobile NULL NULL NULL NULL Mike Wanaswa NULL 790175045 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 22:28:09+00 2043-12-22 22:28:09+00 1 1 NULL 29559.82 2026-04-23 11:16:37.277518+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
75 862798050523204 Amani Kazungu - KCY 084X JC400P aotomobile KCY 084X KCY 084X Probox automobile NULL NULL NULL NULL Amani Kazungu NULL 707892547 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 06:18:20+00 2042-01-16 23:59:59+00 1 1 NULL 66955.70 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
76 862798050523295 Emmanuel Luseno - KDS 453 Y JC400P aotomobile KDS 453 Y KDS 453 Y Pick-Up automobile NULL NULL NULL NULL Emmanuel Luseno NULL 700242474 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 14:39:50+00 2033-12-22 23:59:59+00 1 1 NULL 37098.35 2026-04-23 11:29:48.369147+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
77 862798050523337 Victor Kimutai - KDS 919Y JC400P aotomobile KDS 919Y KDS 919Y Probox automobile NULL NULL NULL NULL Victor Kimutai NULL 700242527 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 18:00:49+00 2043-12-22 18:00:49+00 1 1 NULL 50756.64 2026-04-23 10:27:13.522675+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
78 862798050523386 George Ochieng' - KDD 684Y JC400P aotomobile KDD 684Y KDD 684Y Probox automobile NULL NULL NULL NULL George Ochieng' NULL 785586834 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 06:36:08+00 2042-01-22 23:59:59+00 1 1 NULL 33979.83 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
79 862798050523527 Allan Owana - KDK 780K JC400P aotomobile KDK 780K KDK 780K Probox automobile NULL NULL NULL NULL Allan Owana NULL 792375024 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-12-03 10:43:41+00 2042-12-03 23:59:59+00 1 1 NULL 109564.95 2026-04-23 10:25:24.360765+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
80 862798050523618 Geoffrey Too - KDM 308S JC400P aotomobile KDM 308S KDM 308S Probox automobile NULL NULL NULL NULL Geoffrey Too NULL 701211625 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-08-15 15:42:32+00 2033-08-15 23:59:59+00 1 1 NULL 26496.50 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
81 862798050523626 Major Simiyu - KDS 949Y JC400P aotomobile KDS 949Y KDS 949Y Probox automobile NULL NULL NULL NULL Major Simiyu NULL 701211892 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 18:05:16+00 2033-12-22 23:59:59+00 1 1 NULL 37042.97 2026-04-23 10:51:18.245194+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
82 862798050523816 Job Ngare - KDM 309S JC400P aotomobile KDM 309S KDM 309S Probox automobile NULL NULL NULL NULL Job Ngare NULL 707936781 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-08-15 14:05:52+00 2033-08-15 23:59:59+00 1 1 NULL 54320.21 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
83 862798050523949 Joseph Kabandi - KCY 076X JC400P aotomobile KCY 076X KCY 076X Probox automobile NULL NULL NULL NULL Joseph Kabandi NULL 113288492 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 05:52:54+00 2042-01-16 23:59:59+00 1 1 NULL 14427.50 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
84 862798050524012 Moses Wambua - KCZ 751V JC400P aotomobile KCZ 751V KCZ 751V Probox automobile NULL NULL NULL NULL Moses Wambua NULL 113313797 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 07:40:10+00 2042-01-16 23:59:59+00 1 1 NULL 26551.46 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
85 862798050524087 Felix Muema - KCZ 223P JC400P aotomobile KCZ 223P KCZ 223P Pick-Up automobile NULL NULL NULL NULL Felix Muema NULL 113973875 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 13:02:24+00 2042-01-16 23:59:59+00 1 1 NULL 11543.26 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
86 862798050524368 862798050524368 JC400P aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-10-29 09:24:53+00 2042-10-29 23:59:59+00 1 1 NULL 169208.91 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
87 862798050524384 Hamisi Pande - KDD 689Y JC400P aotomobile KDD 689Y KDD 689Y Probox automobile NULL NULL NULL 0.00 Hamisi Pande NULL 701211744 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 05:49:19+00 2042-01-22 23:59:59+00 1 1 NULL 13685.18 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
88 862798050524392 Ndegwa Dancun - KCG 669W JC400P aotomobile KCG 669W KCG 669W Probox automobile NULL NULL NULL NULL Ndegwa Dancun NULL 113799173 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 09:43:10+00 2042-01-16 23:59:59+00 1 1 NULL 13638.25 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
89 862798050524426 Amani Sulubu - KCY 090X JC400P aotomobile KCY 090X KCY 090X Probox automobile NULL NULL NULL NULL Amani Sulubu NULL 113823350 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-16 08:56:25+00 2042-01-16 23:59:59+00 1 1 NULL 14243.83 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
90 862798050524533 Leonard Nzai - KDM 306S JC400P aotomobile KDM 306S KDM 306S Probox automobile NULL NULL NULL NULL Leonard Nzai NULL 703487162 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-08-21 08:22:12+00 2033-08-21 23:59:59+00 1 1 NULL 68942.41 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
91 862798050524558 Mutuku Joseph - KDC 739F JC400P aotomobile KDC 739F KDC 739F Probox automobile NULL NULL NULL NULL Mutuku Joseph NULL 100858817 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 10:38:25+00 2042-01-22 23:59:59+00 1 1 NULL 23711.63 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
92 862798050524566 Makanda Andrew - KCZ 155P JC400P aotomobile KCZ 155P KCZ 155P Pick-Up automobile NULL NULL NULL NULL Makanda Andrew NULL 758781444 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-22 09:47:33+00 2042-01-22 23:59:59+00 1 1 NULL 31663.30 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
93 862798050524608 Peter Mbugua - KDK 728K JC400P aotomobile KDK 728K KDK 728K Probox automobile NULL NULL NULL NULL Peter Mbugua NULL 706742413 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-12-03 12:11:32+00 2042-12-03 23:59:59+00 1 1 NULL 7219.31 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
94 862798050524657 Felix Andole - KDC 207R JC400P aotomobile KDC 207R KDC 207R Probox automobile NULL NULL NULL NULL Felix Andole NULL 758689195 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 07:17:47+00 2042-01-22 23:59:59+00 1 1 NULL 46233.99 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
95 862798050524681 Mutuku Antony - KDK 732K JC400P aotomobile KDK 732K KDK 732K Probox automobile NULL NULL NULL NULL Mutuku Antony NULL 796275746 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-12-06 13:37:49+00 2042-12-06 23:59:59+00 1 1 NULL 14993.36 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
96 862798050524707 Garage - KCE 699F JC400P aotomobile KCE 699F KCE 699F Probox automobile NULL NULL NULL NULL Garage NULL 110525751 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 07:58:49+00 2042-01-15 23:59:59+00 1 1 NULL 34715.97 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
97 862798050524897 Cornelius Kimutai - KCU 938R JC400P aotomobile KCU 938R KCU 938R Van automobile NULL NULL NULL NULL Cornelius Kimutai NULL 114924404 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-22 09:03:40+00 2042-01-22 23:59:59+00 1 1 NULL 12668.43 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
98 862798050525068 Samuel Ng'ang'a - KDE 264M JC400P aotomobile KDE 264M KDE 264M Probox automobile NULL NULL NULL NULL Samuel Ng'ang'a NULL 768658564 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 13:33:42+00 2033-12-22 23:59:59+00 1 1 NULL 12299.13 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
99 862798050525225 Sadique Wakayula - KDC 490Q JC400P aotomobile KDC 490Q KDC 490Q Crane truck NULL NULL NULL NULL Sadique Wakayula NULL 768652386 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-22 20:52:08+00 2043-12-22 20:52:08+00 1 1 NULL 19138.05 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
100 862798050525266 Dickson Jaoko - KDK 815R JC400P aotomobile KDK 815R KDK 815R Probox automobile NULL NULL NULL NULL Dickson Jaoko NULL 706665867 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-06-21 07:50:00+00 2033-06-21 23:59:59+00 1 1 NULL 63754.71 2026-04-23 13:50:24.21992+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
101 862798050525423 Makori John - KDB 585E JC400P aotomobile KDB 585E KDB 585E Probox automobile NULL NULL NULL NULL Makori John NULL 701211724 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 10:59:19+00 2042-01-15 23:59:59+00 1 1 NULL 48804.83 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
102 862798050525589 Simon Kamau - KCE 090R JC400P aotomobile KCE 090R KCE 090R Probox automobile NULL NULL NULL NULL Simon Kamau NULL 796276387 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-19 10:10:04+00 2042-01-19 23:59:59+00 1 1 NULL 15874.39 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
103 862798050525605 John Ondego - KCA 542Q JC400P aotomobile KCA 542Q KCA 542Q Probox automobile NULL NULL NULL NULL John Ondego NULL 110526783 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 05:56:11+00 2042-01-15 23:59:59+00 1 1 NULL 23976.94 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
104 862798050525613 Kennedy Chege - KCQ 618K JC400P aotomobile KCQ 618K KCQ 618K Probox automobile NULL NULL NULL NULL Kennedy Chege NULL 729994247 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-16 05:21:05+00 2042-01-16 23:59:59+00 1 1 NULL 12804.24 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
105 862798050525670 Gabriel Musumba - KCE 690F JC400P aotomobile KCE 690F KCE 690F Probox automobile NULL NULL NULL NULL Gabriel Musumba NULL 701211996 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2022-01-15 06:40:01+00 2042-01-15 23:59:59+00 1 1 NULL 20110.93 2026-04-24 05:34:23.167312+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
106 862798050525753 Noel Merengeni - KCY 838X JC400P aotomobile KCY 838X KCY 838X Probox automobile NULL NULL NULL NULL Noel Merengeni NULL NULL NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2022-01-15 05:24:00+00 2042-01-15 23:59:59+00 1 1 NULL 14596.59 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
107 862798050525837 Kennedy Ondieki - KCU 237Z JC400P aotomobile KCU 237Z KCU 237Z Probox automobile NULL NULL NULL NULL Kennedy Ondieki NULL 113669852 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2023-12-21 19:32:44+00 2033-12-21 23:59:59+00 1 1 NULL NULL 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
108 862798050525951 Wright Oseko - KCG 668W JC400P aotomobile KCG 668W KCG 668W Probox automobile NULL NULL NULL NULL Wright Oseko NULL 741943212 NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2022-01-15 09:36:45+00 2042-01-15 23:59:59+00 1 1 NULL 13116.00 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
109 862798050526165 Wilfred Kinyanjui - KCU 729C JC400P aotomobile KCU 729C KCU 729C Crane truck NULL NULL NULL NULL Wilfred Kinyanjui NULL 790564929 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-11-26 10:17:19+00 2033-11-26 23:59:59+00 1 1 NULL 24270.20 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
110 862798050526231 Rashid Hassan - KDM 840V JC400P aotomobile KDM 840V KDM 840V Probox automobile NULL NULL NULL NULL Rashid Hassan NULL 790175526 NULL NULL Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2023-12-22 22:36:15+00 2043-12-22 22:36:15+00 1 1 NULL 45418.38 2026-04-23 10:29:41.575467+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
111 862798050526256 Ian Dancun - KDT 923R JC400P aotomobile KDT 923R KDT 923R Probox automobile NULL NULL NULL NULL Ian Dancun NULL 794873610 NULL NULL Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2023-12-22 19:37:24+00 2043-12-22 19:37:24+00 1 1 NULL 11093.11 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
112 862798052707888 Benjamin Ananda - KDV 438W JC400P aotomobile KDV 438W KDV 438W Probox automobile NULL NULL NULL NULL Benjamin Ananda NULL 758047312 89254021414206816980 639021410681698 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-15 07:39:23+00 2035-12-15 23:59:59+00 1 1 NULL 8720.87 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
113 862798052707896 John Mbugua - KDW 573B JC400P aotomobile KDW 573B KDW 573B Probox automobile NULL NULL NULL NULL John Mbugua NULL NULL 89254021414206816725 639021410681672 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-30 14:48:17+00 2036-01-30 23:59:59+00 1 1 NULL 515.16 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
114 862798052707946 Tom Wekesa/OSP-KCY 930Y_CAM JC400P aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL 0758047806 89254021414206816766 639021410681676 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-20 21:02:13+00 2036-01-20 23:59:59+00 1 1 NULL 10079.17 2026-04-23 10:25:24.363965+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
115 862798052708035 862798052708035 JC400P aotomobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL NULL NULL fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group NULL NULL 1 1 NULL NULL 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
116 862798052708068 Dominic Wambua - KDV 683Z JC400P aotomobile KDV 683Z KDV 683Z Probox automobile NULL NULL NULL NULL Dominic Wambua NULL 758048043 89254021414206816964 639021410681696 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-24 09:20:09+00 2036-01-24 23:59:59+00 1 1 NULL 4438.55 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
117 862798052708076 Albert Mutwiri - KDV 437W JC400P aotomobile NULL KDV 437W Probox automobile NULL NULL NULL NULL Albert Mutwiri NULL 758047094 89254021414206816782 639021410681678 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-13 15:03:30+00 2035-12-13 23:59:59+00 1 1 NULL 5575.64 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
118 862798052708167 Levine Wasike - KDV 439W JC400P aotomobile KDV 439W KDV 439W Probox automobile NULL NULL NULL NULL Levine Wasike NULL 758046738 89254021414206816741 639021410681674 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 19:49:29+00 2035-12-13 23:59:59+00 1 1 NULL 4601.08 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
119 862798052708282 Godffrey Nandwa - KCN 496A JC400P aotomobile KCN 496A KCN 496A Probox automobile NULL NULL NULL NULL Godffrey Nandwa NULL 758047934 89254021414206816865 639021410681686 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-25 18:55:54+00 2036-01-25 23:59:59+00 1 1 NULL 7040.60 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
120 862798052713654 Garage/ISP_KCL 502T_CAM JC400P aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL 0780215879 89254035061001753803 639035060175380 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-09-02 10:09:57+00 2035-09-02 23:59:59+00 1 1 NULL 5199.72 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
121 862798052713696 862798052713696 JC400P aotomobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL 89254021394215205906 639021391520590 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-09-02 10:20:58+00 2035-09-02 23:59:59+00 1 1 NULL 6214.49 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
122 862798052713761 Management_Mazda - KDU 613A JC400P aotomobile KDU 613A KDU 613A Mazda automobile NULL NULL NULL NULL Management_Mazda NULL 790176786 89254021394215205955 639021391520595 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-09 15:49:26+00 2035-07-09 23:59:59+00 1 1 NULL 9262.78 2026-04-23 16:40:48.879666+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
123 862798052713779 Benard Kimutai - KDN 759G JC400P aotomobile KDN 759G KDN 759G Probox automobile NULL NULL NULL NULL Benard Kimutai NULL 752143258 89254035061001753860 639035060175386 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-23 11:15:59+00 2035-08-23 23:59:59+00 1 1 NULL 5344.24 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
124 862798052713811 James Onyango - KDU 613B JC400P aotomobile KDU 613B KDU 613B Probox automobile NULL NULL NULL NULL James Onyango NULL 790176542 89254021394215205880 639021391520588 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-09 19:24:14+00 2035-07-09 23:59:59+00 1 1 NULL 9657.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
125 862798052713837 Kennedy Ondieki - KCU 237Z JC400P aotomobile KCU 237Z KCU 237Z Probox automobile NULL NULL NULL NULL Kennedy Ondieki NULL 113669852 89254021414206327855 639021410632785 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-10-08 14:55:23+00 2035-10-08 23:59:59+00 1 1 NULL 9346.02 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
126 862798052713985 Timothy Gitau - KDT 916R JC400P aotomobile KDT 916R KDT 916R Probox automobile NULL NULL NULL NULL Timothy Gitau NULL 768696668 89254021394274518892 639021397451889 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-08-02 18:21:23+00 2035-08-02 23:59:59+00 1 1 NULL 19998.22 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
127 862798052714066 862798052714066 JC400P aotomobile NULL NULL Probox automobile NULL NULL NULL NULL NULL NULL NULL 89254021414206378684 639021410637868 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-11-21 17:44:44+00 2035-11-21 23:59:59+00 1 1 NULL 10755.28 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
128 862798052715220 Rofas Njagi - KDT 728R JC400P aotomobile KDT 728R KDT 728R Probox automobile NULL NULL NULL NULL Rofas Njagi NULL 704573658 89254021334258495873 639021335849587 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-16 07:09:25+00 2035-07-16 23:59:59+00 1 1 NULL 16385.58 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
129 865135061035133 Major Simiyu - KDS 949Y X3 aotomobile KDS 949Y KDS 949Y Probox automobile NULL NULL NULL NULL Major Simiyu NULL 768696642 89254021394274518918 639021397451891 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 13:14:33+00 2035-08-02 23:59:59+00 1 1 NULL 25089.98 2026-04-23 12:07:56.044395+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
130 865135061035653 Richardson Komu - KDT 923R X3 aotomobile KDT 923R KDT 923R Probox automobile NULL NULL NULL NULL Richardson Komu NULL 768697292 89254021394274518942 639021397451894 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-08-02 08:11:46+00 2035-08-02 23:59:59+00 1 1 NULL 23556.65 2026-04-23 10:24:50.340401+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
131 865135061035778 John Kimeria - KDS 525D X3 aotomobile KDS 525D KDS 525D Crane truck NULL NULL NULL NULL John Kimeria NULL 790176738 89254021394215205922 639021391520592 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-11 05:50:36+00 2035-07-11 23:59:59+00 1 1 NULL 17653.96 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
132 865135061036164 Brian Njenga - KMFF 113Z X3 aotomobile KMFF 113Z KMFF 113Z Motorbike mtc NULL NULL NULL NULL Brian Njenga NULL 768696705 89254021394274518850 639021397451885 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 10:06:46+00 2035-07-31 23:59:59+00 1 1 NULL 22990.33 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
133 865135061037980 Emmanuel Luseno - KDS 453Y X3 aotomobile KDS 453Y KDS 453Y Pick-Up automobile NULL NULL NULL NULL Emmanuel Luseno NULL 790176734 89254021394215205856 639021391520585 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-15 06:30:34+00 2035-07-15 23:59:59+00 1 1 NULL 42609.03 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
134 865135061042261 Kelvin Wambugu - KDR 592N X3 aotomobile KDR 592N KDR 592N Probox automobile NULL NULL NULL NULL Kelvin Wambugu NULL 797680464 89254021334258159693 639021335815969 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-10 10:23:44+00 2035-07-10 23:59:59+00 1 1 NULL 18755.66 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
135 865135061043079 Mike Wanaswa - KDT 724R X3 aotomobile KDT 724R KDT 724R Probox automobile NULL NULL NULL NULL Mike Wanaswa NULL 768696664 89254021394274518959 639021397451895 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 12:16:11+00 2035-08-02 23:59:59+00 1 1 NULL 27470.11 2026-04-23 11:16:35.682194+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
136 865135061043426 Geoffrey Karanja - KMGS 239H X3 aotomobile KMGS 239H KMGS 239H Motorbike mtc NULL NULL NULL NULL Geoffrey Karanja NULL 768696658 89254021394274518926 639021397451892 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-22 13:32:25+00 2035-08-22 23:59:59+00 1 1 NULL 21267.01 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
137 865135061047435 Management_Mazda - KDU 613A X3 aotomobile KDU 613A KDU 613A Mazda automobile NULL NULL NULL NULL Management_Mazda NULL 790175971 89254021394215205971 639021391520597 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-09 08:02:26+00 2035-07-09 23:59:59+00 1 1 NULL 9761.38 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
138 865135061048276 Victor Kimutai - KDS 919Y X3 aotomobile KDS 919Y KDS 919Y Probox automobile NULL NULL NULL NULL Victor Kimutai NULL 768696755 89254021394274518900 639021397451890 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 07:38:01+00 2035-08-02 23:59:59+00 1 1 NULL 23296.79 2026-04-23 10:54:41.63532+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
139 865135061048300 KMGR 409U HENRY JAZZ NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-24 04:30:20.231102+00 2026-04-24 04:30:20.231102+00 NULL NULL NULL NULL NULL NULL NULL
140 865135061048466 Samuel Muriithy - KDR 594N X3 aotomobile KDR 594N KDR 594N Probox automobile NULL NULL NULL NULL Samuel Muriithy NULL 797680395 89254021334258159628 639021335815962 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-24 09:37:31+00 2035-07-24 23:59:59+00 1 1 NULL 27634.10 2026-04-23 11:43:39.178819+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
141 865135061048615 Office-KMDG 902Z X3 aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL 0768697276 89254021394274518876 639021397451887 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 09:59:43+00 2035-07-31 23:59:59+00 1 1 NULL 5721.21 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
142 865135061048953 Timothy Gitau - KDT 916R X3 aotomobile KDT 916R KDT 916R Probox automobile NULL NULL NULL NULL Timothy Gitau NULL 768697056 89254021394274518967 639021397451896 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2025-08-02 08:48:05+00 2035-08-02 23:59:59+00 1 1 NULL 28536.23 2026-04-23 10:53:31.102315+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
143 865135061049001 Parked - KMGK 596V X3 aotomobile KMGK 596V KMGK 596V Motorbike mtc NULL NULL NULL NULL Parked NULL 768697064 89254021394274518884 639021397451888 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-31 08:40:18+00 2035-07-31 23:59:59+00 1 1 NULL 20612.89 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
144 865135061053714 Samuel Kihara - KMEL 225X X3 aotomobile KMEL 225X KMEL 225X Motorbike mtc NULL NULL NULL NULL Samuel Kihara NULL 768696832 89254021394274518934 639021397451893 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-08-02 13:51:47+00 2035-08-02 23:59:59+00 1 1 NULL 26897.18 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
145 865135061053748 Rashid Hassan - KDM 840V X3 aotomobile KDM 840V KDM 840V Probox automobile NULL NULL NULL NULL Rashid Hassan NULL 768445963 89254021334212352574 639021331235257 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-07-10 13:54:11+00 2035-07-10 23:59:59+00 1 1 NULL 26612.42 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
146 865135061054548 James Onyango - KDU 613B X3 aotomobile KDU 613B KDU 613B Probox automobile NULL NULL NULL NULL James Onyango NULL 790175997 89254021394215205948 639021391520594 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-09 07:11:15+00 2035-07-09 23:59:59+00 1 1 NULL 13446.05 2026-04-23 10:26:24.667167+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
147 865135061054555 Rofas Njagi - KDT 728R X3 aotomobile KDT 728R KDT 728R Probox automobile NULL NULL NULL NULL Rofas Njagi NULL 790176726 89254021394215205823 639021391520582 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-07-16 06:44:33+00 2035-07-16 23:59:59+00 1 1 NULL 27250.80 2026-04-23 10:25:21.085437+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
148 865135061559538 FRED KMGW 538W HULETI NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-23 10:42:18.5831+00 2026-04-23 10:42:18.5831+00 NULL NULL NULL NULL NULL NULL NULL
149 865135061562722 John Mbugua - KDW 573B X3 aotomobile KDW 573B KDW 573B Probox automobile NULL NULL NULL NULL John Mbugua NULL 758052508 89254021414206816832 639021410681683 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-30 06:53:57+00 2036-01-30 23:59:59+00 1 1 NULL 4488.19 2026-04-23 10:25:38.887433+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
150 865135061562847 Levine Wasike - KDV 439W X3 aotomobile KDV 439W KDV 439W Probox automobile NULL NULL NULL NULL Levine Wasike NULL 758047032 89254021414206816840 639021410681684 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2025-12-13 11:14:14+00 2035-12-13 23:59:59+00 1 1 NULL 7880.92 2026-04-23 10:35:50.779597+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
151 865135061563282 X3-63282 X3 aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL 8925610001837573427F 641101970467668 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-14 07:20:10+00 2036-02-14 23:59:59+00 1 1 NULL 4758.32 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
152 865135061563415 Barack Orwa - KDW 781E X3 aotomobile KDW 781E KDW 781E Vazel automobile NULL NULL NULL NULL Barack Orwa NULL 758052541 89254021414206816931 639021410681693 Fireside_MSA Fireside Group MSA 9d0927d235e44fe7abf254902fc68921 Default group 2026-01-13 12:37:42+00 2036-01-13 23:59:59+00 1 1 NULL 4165.95 2026-04-23 11:22:00.676215+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
153 865135061563423 Joel Ntumba - UMA 826AB X3 aotomobile UMA 826AB UMA 826AB Motorbike mtc NULL NULL NULL NULL Joel Ntumba NULL 119051036 89254021414206652690 639021410665269 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-28 13:55:39+00 2036-01-28 23:59:59+00 1 1 NULL 1174.05 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
154 865135061563597 Dominic Wambua - KDV 683Z X3 aotomobile KDV 683Z KDV 683Z Probox automobile NULL NULL NULL NULL Dominic Wambua NULL 758052405 89254021414206816733 639021410681673 Fireside@HQ Fireside Telematics 6ef0b0fc2d964b358b70dc2cfcbc5b7e Default group 2026-01-30 06:55:35+00 2036-01-30 23:59:59+00 1 1 NULL 6790.53 2026-04-23 10:25:40.125927+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
155 865135061563639 Benjamin Ananda - KDV 438W X3 aotomobile KDV 438W KDV 438W Probox automobile NULL NULL NULL NULL Benjamin Ananda NULL 758047065 89254021414206816683 639021410681668 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 16:02:37+00 2035-12-13 23:59:59+00 1 1 NULL 14446.33 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
156 865135061564280 Rodin Kiberu - UMA 011EK X3 aotomobile UMA 011EK UMA 011EK Motorbike mtc NULL NULL NULL NULL Rodin Kiberu NULL 118081642 89254021414206817244 639021410681724 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-01-28 13:13:57+00 2036-01-28 23:59:59+00 1 1 NULL 841.39 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
157 865135061564470 Silvanus Kipkorir - KDV 064S X3 aotomobile KDV 064S KDV 064S Probox automobile NULL NULL NULL NULL Silvanus Kipkorir NULL 113669866 89254021414206378718 639021410637871 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-11-21 16:49:17+00 2035-11-21 23:59:59+00 1 1 NULL 23869.16 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
158 865135061568968 X3-68968 X3 aotomobile NULL NULL NULL automobile NULL NULL NULL NULL NULL NULL NULL 89254021414206816915 639021410681691 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-03-11 06:19:14+00 2036-03-11 23:59:59+00 1 1 NULL 16.23 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
159 865135061569123 Albert Mutwiri - KDV 437W X3 aotomobile KDV 437W KDV 437W Probox automobile NULL NULL NULL NULL Albert Mutwiri NULL 758047101 89254021414206816881 639021410681688 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-12-13 14:26:17+00 2035-12-13 23:59:59+00 1 1 NULL 13032.60 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
160 865135061569131 UMA 418EK X3 aotomobile UMA 418EK UMA 418EK NULL automobile NULL NULL NULL NULL UG NULL 256792997053 8925610001837573385F 641101970467664 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-26 08:15:44+00 2036-02-26 23:59:59+00 1 1 NULL 2333.45 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
161 865135061569479 UMA 382EK X3 aotomobile UMA 382EK UMA 382EK NULL automobile NULL NULL NULL NULL UG NULL 256792997079 8925610001837573419F 641101970467667 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2026-02-26 08:21:10+00 2036-02-26 23:59:59+00 1 1 NULL 1954.86 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL
162 865135061578553 X3-78553 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 unknown NULL NULL 2026-04-23 15:30:19.981271+00 2026-04-23 15:30:19.981271+00 NULL NULL NULL NULL NULL NULL NULL
163 865135061581904 Robert Kipruto - KDV 072L X3 aotomobile KDV 072L KDV 072L Probox automobile NULL NULL NULL NULL Robert Kipruto NULL 114149576 89254021264261503993 639021266150399 fireside Fireside Group HQ 2f1acaef6c884214b4598719180fe68d Default group 2025-11-21 15:30:29+00 2035-11-21 23:59:59+00 1 1 NULL 15252.84 2026-04-23 10:23:56.546784+00 2026-04-24 07:43:45.210628+00 2026-04-24 07:43:45.210628+00 NULL NULL NULL NULL NULL NULL

View file

@ -1,69 +0,0 @@
-- =============================================================
-- TRACKSOLID DWH CONTROL SCHEMA
-- Target Database: tracksolid_dwh
-- Purpose: Watermarks + per-run audit log for the n8n DWH pipeline
-- Applies after: 260423_dwh_ddl_v1.sql (requires dwh_owner role + grafana_ro role)
-- =============================================================
BEGIN;
-- 1. CONTROL SCHEMA
-- Owned by dwh_owner to match bronze/silver/gold ownership convention from 260423.
CREATE SCHEMA IF NOT EXISTS dwh_control AUTHORIZATION dwh_owner;
GRANT USAGE ON SCHEMA dwh_control TO grafana_ro;
-- 2. PERMISSIONS (dwh_owner writes, grafana_ro reads)
-- Existing default privileges from 260423 only cover bronze/silver/gold; extend to dwh_control.
ALTER DEFAULT PRIVILEGES FOR ROLE dwh_owner IN SCHEMA dwh_control
GRANT SELECT ON TABLES TO grafana_ro;
-- 3. EXTRACT WATERMARKS
-- One row per incremental table. Updated by Workflow 2 after a successful load commit.
-- last_extracted_at is the UPPER bound used in the most recent successful extract,
-- so the next run uses `WHERE <ts_col> > last_extracted_at AND <ts_col> <= :run_started_at`.
SET ROLE dwh_owner;
CREATE TABLE IF NOT EXISTS dwh_control.extract_watermarks (
table_name TEXT PRIMARY KEY,
last_extracted_at TIMESTAMPTZ NOT NULL DEFAULT '2026-01-01T00:00:00Z',
last_loaded_at TIMESTAMPTZ,
rows_loaded_last_run INT,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- 4. EXTRACT RUN AUDIT LOG
-- One row per table per cron tick. Lifecycle: extracting → uploaded → loading → loaded (or failed).
-- Failures retain error_message; the CSV stays in dwh/exports/ for the next run to pick up.
CREATE TABLE IF NOT EXISTS dwh_control.extract_runs (
run_id BIGSERIAL PRIMARY KEY,
table_name TEXT NOT NULL,
run_started_at TIMESTAMPTZ NOT NULL,
run_finished_at TIMESTAMPTZ,
rows_extracted INT,
rows_loaded INT,
csv_path TEXT,
status TEXT CHECK (status IN ('extracting','uploaded','loading','loaded','failed')),
error_message TEXT
);
CREATE INDEX IF NOT EXISTS idx_extract_runs_table_time
ON dwh_control.extract_runs (table_name, run_started_at DESC);
CREATE INDEX IF NOT EXISTS idx_extract_runs_status_time
ON dwh_control.extract_runs (status, run_finished_at DESC);
-- 5. SEED WATERMARKS
-- One row per incremental table. Snapshot tables (devices, live_positions) do not need
-- watermarks and are intentionally omitted.
INSERT INTO dwh_control.extract_watermarks (table_name) VALUES
('position_history'),
('trips'),
('alarms'),
('parking_events'),
('device_events'),
('ingestion_log')
ON CONFLICT (table_name) DO NOTHING;
RESET ROLE;
COMMIT;

View file

@ -1,63 +0,0 @@
-- =============================================================
-- BRONZE CONSTRAINTS AUDIT
-- Target Database: tracksolid_dwh
-- Purpose: Assert that every ON CONFLICT target used by Workflow 2
-- (dwh_load_bronze) is backed by a PRIMARY KEY or UNIQUE
-- constraint in the bronze schema. Fails loudly if a future
-- DDL edit removes a key the ingestion pipeline depends on.
-- Applies after: 260423_dwh_ddl_v1.sql
-- Idempotent: pure assertion, no DDL changes.
-- =============================================================
BEGIN;
DO $$
DECLARE
missing TEXT := '';
expected RECORD;
BEGIN
-- Each row asserts: bronze.<table> has a PK/UNIQUE matching <cols>.
-- If the pipeline's ON CONFLICT clause ever diverges from this list,
-- update both here and the n8n load workflow in lockstep.
FOR expected IN
SELECT * FROM (VALUES
('devices', 'imei'),
('live_positions', 'imei'),
('position_history', 'imei,gps_time'),
('trips', 'id'),
('alarms', 'id'),
('parking_events', 'id'),
('device_events', 'id'),
('ingestion_log', 'id')
) AS t(table_name, cols)
LOOP
IF NOT EXISTS (
SELECT 1
FROM pg_constraint c
JOIN pg_class r ON r.oid = c.conrelid
JOIN pg_namespace n ON n.oid = r.relnamespace
CROSS JOIN LATERAL (
SELECT string_agg(a.attname, ',' ORDER BY k.ord) AS keycols
FROM unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
JOIN pg_attribute a
ON a.attrelid = c.conrelid AND a.attnum = k.attnum
) AS cols
WHERE n.nspname = 'bronze'
AND r.relname = expected.table_name
AND c.contype IN ('p','u')
AND cols.keycols = expected.cols
) THEN
missing := missing
|| format(E'\n - bronze.%s missing PK/UNIQUE on (%s)',
expected.table_name, expected.cols);
END IF;
END LOOP;
IF length(missing) > 0 THEN
RAISE EXCEPTION E'Bronze constraint audit FAILED:%s', missing;
END IF;
RAISE NOTICE 'Bronze constraint audit OK: all 8 ON CONFLICT targets backed by PK/UNIQUE.';
END$$;
COMMIT;

View file

@ -1,66 +0,0 @@
-- =============================================================
-- DWH ROLES AUDIT
-- Target Database: tracksolid_dwh
-- Purpose: Assert that the n8n DWH pipeline's role contract holds:
-- - dwh_owner exists (writes bronze + dwh_control)
-- - grafana_ro exists (reads bronze + silver + gold + dwh_control)
-- - grafana_ro has CONNECT on the database
-- - grafana_ro has USAGE on every schema it needs
-- Applies after: 260423_dwh_ddl_v1.sql, 261001_dwh_control.sql
-- Idempotent: pure assertion, no CREATE ROLE or GRANT statements.
--
-- Why this file exists: 260423 creates both roles and grants bronze/silver/gold;
-- 261001 grants dwh_control. This file is a single checkpoint that verifies
-- those prior migrations were applied in the right order, and fails loudly
-- if anything is missing before the pipeline goes live.
--
-- Password rotation and sslmode=require enforcement are out-of-band:
-- rotate via ALTER ROLE ... PASSWORD ... in a psql superuser session,
-- enforce SSL via the n8n credential (sslmode=require) — not SQL-level.
-- =============================================================
BEGIN;
DO $$
DECLARE
missing TEXT := '';
r RECORD;
BEGIN
-- 1. Roles exist
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'dwh_owner') THEN
missing := missing || E'\n - role dwh_owner missing (expected from 260423)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
missing := missing || E'\n - role grafana_ro missing (expected from 260423)';
END IF;
-- 2. grafana_ro CONNECT on this database
IF NOT has_database_privilege('grafana_ro', current_database(), 'CONNECT') THEN
missing := missing
|| format(E'\n - grafana_ro lacks CONNECT on database %s',
current_database());
END IF;
-- 3. grafana_ro USAGE on every schema the pipeline / dashboards touch
FOR r IN
SELECT unnest(ARRAY['bronze','silver','gold','dwh_control']) AS schema_name
LOOP
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = r.schema_name) THEN
missing := missing
|| format(E'\n - schema %s missing (expected from 260423/261001)',
r.schema_name);
ELSIF NOT has_schema_privilege('grafana_ro', r.schema_name, 'USAGE') THEN
missing := missing
|| format(E'\n - grafana_ro lacks USAGE on schema %s',
r.schema_name);
END IF;
END LOOP;
IF length(missing) > 0 THEN
RAISE EXCEPTION E'DWH roles audit FAILED:%s', missing;
END IF;
RAISE NOTICE 'DWH roles audit OK: dwh_owner + grafana_ro present with expected grants.';
END$$;
COMMIT;

View file

@ -1,79 +0,0 @@
-- =============================================================
-- DWH OBSERVABILITY VIEWS
-- Target Database: tracksolid_dwh
-- Purpose: Surface pipeline health for Grafana dashboards. Three views,
-- one concern each:
-- v_table_freshness — how long since each table was last loaded
-- v_recent_failures — failed runs in the last 24h
-- v_watermark_lag — per-table watermark vs. now
-- Applies after: 261001_dwh_control.sql
-- Readability: owned by dwh_owner → grafana_ro inherits SELECT via the
-- ALTER DEFAULT PRIVILEGES set in 261001. Explicit GRANT below
-- covers the case where defaults were set AFTER this file runs.
-- =============================================================
BEGIN;
SET ROLE dwh_owner;
-- 1. FRESHNESS
-- One row per table that has ever loaded successfully. `lag` drives the
-- freshness panel; `loads_last_24h` sanity-checks the cron cadence.
CREATE OR REPLACE VIEW dwh_control.v_table_freshness AS
SELECT
table_name,
MAX(run_finished_at) AS last_loaded_at,
NOW() - MAX(run_finished_at) AS lag,
COUNT(*) FILTER (WHERE run_started_at > NOW() - INTERVAL '24 hours') AS loads_last_24h
FROM dwh_control.extract_runs
WHERE status = 'loaded'
GROUP BY table_name;
COMMENT ON VIEW dwh_control.v_table_freshness IS
'Per-table load lag. Alert when lag > 4h during active hours (05:0023:00 EAT).';
-- 2. RECENT FAILURES
-- Failures retain error_message; the CSV stays in dwh/exports/ for the next
-- scheduled run to retry. Panel should show run_id so operators can grep logs.
CREATE OR REPLACE VIEW dwh_control.v_recent_failures AS
SELECT
run_id,
table_name,
run_started_at,
run_finished_at,
csv_path,
error_message
FROM dwh_control.extract_runs
WHERE status = 'failed'
AND run_started_at > NOW() - INTERVAL '24 hours'
ORDER BY run_started_at DESC;
COMMENT ON VIEW dwh_control.v_recent_failures IS
'Failed extract/load runs in the last 24h. Alert on any row.';
-- 3. WATERMARK LAG
-- Distinguishes "pipeline ran but found nothing" (load_lag small, extract_lag
-- growing) from "pipeline is stuck" (both lags growing). Snapshot tables are
-- not in extract_watermarks so they do not appear here — that is intentional.
CREATE OR REPLACE VIEW dwh_control.v_watermark_lag AS
SELECT
table_name,
last_extracted_at,
last_loaded_at,
rows_loaded_last_run,
NOW() - last_loaded_at AS load_lag,
NOW() - last_extracted_at AS extract_lag
FROM dwh_control.extract_watermarks;
COMMENT ON VIEW dwh_control.v_watermark_lag IS
'Per-table watermark position vs. now. Incremental tables only (6 rows).';
RESET ROLE;
-- Explicit grants: defensive in case ALTER DEFAULT PRIVILEGES from 261001
-- was not in effect when these views were created.
GRANT SELECT ON dwh_control.v_table_freshness TO grafana_ro;
GRANT SELECT ON dwh_control.v_recent_failures TO grafana_ro;
GRANT SELECT ON dwh_control.v_watermark_lag TO grafana_ro;
COMMIT;

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -1,24 +1,8 @@
""" """
import_drivers_csv.py Fireside Communications · Driver & Vehicle CSV Import import_drivers_csv.py Fireside Communications · Driver & Vehicle CSV Import
One-shot script: reads the snake_case Fireside Group vehicle CSV One-shot script: reads 20260414_FS__Logistics - final_fixed.csv, compares
(`20260427_FSG_Vehicles_mitieng.csv`), compares each row against the each row against the current tracksolid.devices values, and updates the DB.
current `tracksolid.devices` values, and updates the DB.
The CSV columns mirror the DB schema directly no inference. Cells with the
literal string "NULL" are treated as missing.
Fields imported (per Phase 0.1 of the Business Analytics redesign plan):
Identity : driver_name, driver_phone, vehicle_number, vehicle_name,
vehicle_models, mc_type, device_name
SIM : sim, iccid, imsi
Lifecycle : activation_time, expiration
Business meta : assigned_city, cost_centre, assigned_route,
vehicle_category, vehicle_brand, fuel_100km, depot_address
`depot_geom` (PostGIS Point) is intentionally NOT imported needs WKT and
isn't present as coordinates in the CSV. Set it via a follow-up migration
when geofences are loaded.
Usage: Usage:
# Dry-run — shows diff, writes nothing # Dry-run — shows diff, writes nothing
@ -33,75 +17,68 @@ Usage:
# Only fill fields that are currently NULL in the DB (never overwrite) # Only fill fields that are currently NULL in the DB (never overwrite)
python import_drivers_csv.py --only-null --apply python import_drivers_csv.py --only-null --apply
# Use a different CSV
python import_drivers_csv.py --csv path/to/file.csv
Pre-requisite: Pre-requisite:
Migrations 02, 05, 06 must be applied (they add the metadata columns). Migration 06 must be applied first (adds assigned_city / cost_centre columns).
""" """
import argparse import argparse
import csv import csv
import os
import sys
import time
from datetime import date
from pathlib import Path from pathlib import Path
from ts_shared_rev import clean, clean_num, clean_ts, get_conn, get_logger from ts_shared_rev import clean, clean_num, clean_ts, get_conn, get_logger
log = get_logger("csv_import") log = get_logger("csv_import")
DEFAULT_CSV_PATH = Path(__file__).parent / "data" / "20260427_FSG_Vehicles_mitieng.csv" CSV_PATH = Path(__file__).parent / "20260414_FS__Logistics - final_fixed.csv"
# Columns fetched from DB for diff comparison. # Columns fetched from DB for comparison
DB_COLS = [ DB_COLS = [
"imei", "imei", "driver_name", "driver_phone", "vehicle_number", "vehicle_name",
# Identity "vehicle_models", "cost_centre", "sim", "iccid", "imsi", "mc_type",
"driver_name", "driver_phone", "vehicle_number", "vehicle_name", "activation_time", "expiration", "device_name", "assigned_city",
"vehicle_models", "mc_type", "device_name",
# SIM
"sim", "iccid", "imsi",
# Lifecycle
"activation_time", "expiration",
# Business metadata (Phase 0.1 additions)
"assigned_city", "cost_centre", "assigned_route",
"vehicle_category", "vehicle_brand", "fuel_100km", "depot_address",
] ]
# Driver Name values that are placeholders — skip writing driver_name for these. # Driver Name values that are placeholders — skip writing driver_name for these
_DRIVER_SKIP = {"identification", "ug"} _DRIVER_SKIP = {"identification", "ug"}
# Columns that need an explicit cast in the UPDATE statement.
_TIMESTAMPTZ_COLS = {"activation_time", "expiration"}
_NUMERIC_COLS = {"fuel_100km"}
def _infer_city(plate: str) -> str | None:
def _read(row: dict, col: str) -> str | None: """Derive assigned_city from license plate prefix."""
"""Read a CSV column treating literal 'NULL'/'None' (case-insensitive) as missing.""" p = (plate or "").strip().upper()
v = clean(row.get(col)) if p.startswith("UMA") or p.startswith("UAG"):
if v is None: return "KLA"
if p.startswith("K"):
return "NBO"
return None return None
return None if v.upper() in ("NULL", "NONE") else v
def _read_num(row: dict, col: str) -> float | None: def _clean_date(v: str) -> str | None:
v = _read(row, col) """Accept YYYY-MM-DD and return as ISO string suitable for TIMESTAMPTZ cast."""
return clean_num(v) if v is not None else None s = (v or "").strip()
if not s:
return None
try:
date.fromisoformat(s)
return s
except ValueError:
return None
def _read_ts(row: dict, col: str) -> str | None: def load_csv() -> dict[str, dict]:
v = _read(row, col)
return clean_ts(v) if v is not None else None
def load_csv(csv_path: Path) -> dict[str, dict]:
"""Load CSV into a dict keyed by IMEI.""" """Load CSV into a dict keyed by IMEI."""
rows: dict[str, dict] = {} rows: dict[str, dict] = {}
with open(csv_path, encoding="utf-8-sig", newline="") as f: with open(CSV_PATH, encoding="utf-8-sig", newline="") as f:
for row in csv.DictReader(f): for row in csv.DictReader(f):
imei = (row.get("imei") or "").strip() imei = (row.get("IMEI") or "").strip()
if not imei: if not imei:
continue continue
rows[imei] = row rows[imei] = row
log.info("CSV loaded: %d rows from %s", len(rows), csv_path.name) log.info("CSV loaded: %d rows from %s", len(rows), CSV_PATH.name)
return rows return rows
@ -125,46 +102,42 @@ def build_update(csv_row: dict, db_row: dict | None, only_null: bool) -> dict[st
When only_null=True, skip any DB column that already has a value. When only_null=True, skip any DB column that already has a value.
The driver_name column is skipped for placeholder-labelled devices. The driver_name column is skipped for placeholder-labelled devices.
""" """
driver_raw = (_read(csv_row, "driver_name") or "") driver_raw = clean(csv_row.get("Driver Name")) or ""
plate = clean(csv_row.get("License Plate No.")) or ""
is_placeholder = driver_raw.lower() in _DRIVER_SKIP is_placeholder = driver_raw.lower() in _DRIVER_SKIP
if driver_raw.lower() == "identification": skip_row = driver_raw.lower() == "identification"
if skip_row:
return {} return {}
proposed: dict[str, object] = { proposed: dict[str, object] = {
# Identity "vehicle_number": clean(plate),
"driver_phone": _read(csv_row, "driver_phone"), "vehicle_name": clean(plate),
"vehicle_number": _read(csv_row, "vehicle_number"), "vehicle_models": clean(csv_row.get("Vehicle Model")),
"vehicle_name": _read(csv_row, "vehicle_name"), "cost_centre": clean(csv_row.get("Department")),
"vehicle_models": _read(csv_row, "vehicle_models"), "sim": clean(csv_row.get("SIM")),
"mc_type": _read(csv_row, "mc_type"), "iccid": clean(csv_row.get("ICCID")),
"device_name": _read(csv_row, "device_name"), "imsi": clean(csv_row.get("IMSI")),
# SIM "mc_type": clean(csv_row.get("Model")),
"sim": _read(csv_row, "sim"), "activation_time": _clean_date(csv_row.get("Activated Date", "")),
"iccid": _read(csv_row, "iccid"), "expiration": _clean_date(csv_row.get("Subscription Expiration", "")),
"imsi": _read(csv_row, "imsi"), "driver_phone": clean(csv_row.get("Telephone")),
# Lifecycle "assigned_city": _infer_city(plate),
"activation_time": _read_ts(csv_row, "activation_time"),
"expiration": _read_ts(csv_row, "expiration"),
# Business metadata
"assigned_city": _read(csv_row, "assigned_city"),
"cost_centre": _read(csv_row, "cost_centre"),
"assigned_route": _read(csv_row, "assigned_route"),
"vehicle_category": _read(csv_row, "vehicle_category"),
"vehicle_brand": _read(csv_row, "vehicle_brand"),
"fuel_100km": _read_num(csv_row, "fuel_100km"),
"depot_address": _read(csv_row, "depot_address"),
} }
if not is_placeholder and driver_raw: if not is_placeholder:
proposed["driver_name"] = driver_raw proposed["driver_name"] = driver_raw or None
# Drop None values — no point sending NULL to overwrite NULL. # Drop None values — no point sending a NULL to overwrite another NULL
proposed = {k: v for k, v in proposed.items() if v is not None} proposed = {k: v for k, v in proposed.items() if v is not None}
if not only_null or db_row is None: if not only_null or db_row is None:
return proposed return proposed
# only_null: drop any column that already has a non-null value in the DB. # only_null: drop any column that already has a non-null value in the DB
return {k: v for k, v in proposed.items() if db_row.get(k) is None} return {
k: v for k, v in proposed.items()
if db_row.get(k) is None
}
def print_diff(imei: str, updates: dict[str, object], db_row: dict | None) -> None: def print_diff(imei: str, updates: dict[str, object], db_row: dict | None) -> None:
@ -175,31 +148,12 @@ def print_diff(imei: str, updates: dict[str, object], db_row: dict | None) -> No
print(f"\n IMEI {imei}:") print(f"\n IMEI {imei}:")
for col, new_val in sorted(updates.items()): for col, new_val in sorted(updates.items()):
old_val = db.get(col) old_val = db.get(col)
if str(old_val) != str(new_val): if old_val != new_val:
print(f" {col:<20} {str(old_val):<30}{new_val}") print(f" {col:<20} {str(old_val):<30}{new_val}")
def _set_clause(col: str) -> str: def run(apply: bool, only_null: bool, filter_imei: str | None) -> None:
"""SQL fragment for `col = ...` honouring per-column casts.""" csv_rows = load_csv()
if col in _TIMESTAMPTZ_COLS:
return f"{col} = COALESCE(%s::TIMESTAMPTZ, {col})"
if col in _NUMERIC_COLS:
# %s already a float; no NULLIF dance needed.
return f"{col} = COALESCE(%s::NUMERIC, {col})"
return f"{col} = COALESCE(NULLIF(%s, ''), {col})"
def _placeholder(col: str) -> str:
"""SQL fragment for a single VALUES placeholder honouring per-column casts."""
if col in _TIMESTAMPTZ_COLS:
return "%s::TIMESTAMPTZ"
if col in _NUMERIC_COLS:
return "%s::NUMERIC"
return "%s"
def run(apply: bool, only_null: bool, filter_imei: str | None, csv_path: Path) -> None:
csv_rows = load_csv(csv_path)
db_rows = load_db_devices() db_rows = load_db_devices()
if filter_imei: if filter_imei:
@ -214,10 +168,12 @@ def run(apply: bool, only_null: bool, filter_imei: str | None, csv_path: Path) -
with conn.cursor() as cur: with conn.cursor() as cur:
for imei, csv_row in csv_rows.items(): for imei, csv_row in csv_rows.items():
db_row = db_rows.get(imei) db_row = db_rows.get(imei)
updates = build_update(csv_row, db_row, only_null) updates = build_update(csv_row, db_row, only_null)
if not updates: if not updates:
driver_raw = (_read(csv_row, "driver_name") or "").lower() # Either an "Identification" placeholder or nothing to change
driver_raw = (csv_row.get("Driver Name") or "").strip().lower()
if driver_raw == "identification": if driver_raw == "identification":
skipped += 1 skipped += 1
else: else:
@ -225,15 +181,20 @@ def run(apply: bool, only_null: bool, filter_imei: str | None, csv_path: Path) -
continue continue
if db_row is None: if db_row is None:
# Device not yet synced from API — insert a stub row so # Device not yet synced from API — insert a stub row now so
# incoming alarms / positions don't trip the FK constraint. # incoming alarms / positions don't trip the FK constraint.
print(f"\n [NEW] IMEI {imei}:") print(f"\n [NEW] IMEI {imei}:")
for col, new_val in sorted(updates.items()): for col, new_val in sorted(updates.items()):
print(f" {col:<20}{new_val}") print(f" {col:<20}{new_val}")
if apply: if apply:
cols = ["imei"] + list(updates.keys()) cols = ["imei"] + list(updates.keys())
vals = [imei] + list(updates.values()) vals = [imei] + [str(v) if v is not None else None for v in updates.values()]
placeholders = ["%s"] + [_placeholder(c) for c in updates.keys()] placeholders = []
for col in cols:
if col in ("activation_time", "expiration"):
placeholders.append("%s::TIMESTAMPTZ")
else:
placeholders.append("%s")
cur.execute( cur.execute(
f"INSERT INTO tracksolid.devices ({', '.join(cols)}) " f"INSERT INTO tracksolid.devices ({', '.join(cols)}) "
f"VALUES ({', '.join(placeholders)}) " f"VALUES ({', '.join(placeholders)}) "
@ -246,10 +207,20 @@ def run(apply: bool, only_null: bool, filter_imei: str | None, csv_path: Path) -
print_diff(imei, updates, db_row) print_diff(imei, updates, db_row)
if apply: if apply:
set_clauses = [_set_clause(c) for c in updates.keys()] set_clauses = []
params = list(updates.values()) params = []
for col, val in updates.items():
if col in ("activation_time", "expiration"):
set_clauses.append(f"{col} = COALESCE(%s::TIMESTAMPTZ, {col})")
else:
set_clauses.append(
f"{col} = COALESCE(NULLIF(%s, ''), {col})"
)
params.append(str(val) if val is not None else None)
set_clauses.append("updated_at = NOW()") set_clauses.append("updated_at = NOW()")
params.append(imei) params.append(imei)
cur.execute( cur.execute(
f"UPDATE tracksolid.devices SET {', '.join(set_clauses)} WHERE imei = %s", f"UPDATE tracksolid.devices SET {', '.join(set_clauses)} WHERE imei = %s",
params, params,
@ -271,19 +242,10 @@ def run(apply: bool, only_null: bool, filter_imei: str | None, csv_path: Path) -
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(description="Import driver/vehicle details from CSV into tracksolid.devices")
description="Import driver/vehicle details from CSV into tracksolid.devices"
)
parser.add_argument("--apply", action="store_true", help="Write changes to DB (default: dry-run)") parser.add_argument("--apply", action="store_true", help="Write changes to DB (default: dry-run)")
parser.add_argument("--only-null", action="store_true", help="Only update fields currently NULL in the DB") parser.add_argument("--only-null", action="store_true", help="Only update fields currently NULL in the DB")
parser.add_argument("--imei", default=None, help="Limit to a single IMEI") parser.add_argument("--imei", default=None, help="Limit to a single IMEI")
parser.add_argument("--csv", default=str(DEFAULT_CSV_PATH),
help=f"Path to the CSV (default: {DEFAULT_CSV_PATH.name})")
args = parser.parse_args() args = parser.parse_args()
csv_path = Path(args.csv) run(apply=args.apply, only_null=args.only_null, filter_imei=args.imei)
if not csv_path.exists():
log.error("CSV file not found: %s", csv_path)
raise SystemExit(1)
run(apply=args.apply, only_null=args.only_null, filter_imei=args.imei, csv_path=csv_path)

View file

@ -38,23 +38,6 @@ REVISIONS (QA-Verified):
Tracksolid sub-accounts. sync_devices, poll_live_positions Tracksolid sub-accounts. sync_devices, poll_live_positions
and poll_parking now iterate every target in TRACKSOLID_TARGETS and poll_parking now iterate every target in TRACKSOLID_TARGETS
and dedupe/scope per-target before writing. and dedupe/scope per-target before writing.
[FIX-M20] Trip enrichment: poll_trips now backfills start_geom/end_geom/
route_geom/waypoints_count from position_history at insert
time, extracts idleSecond, reverse-geocodes start/end addresses
(Nominatim), and caches vehicle_plate from devices. Closes the
NULL-column gaps that were inherent to jimi.device.track.mileage
(it does not return coordinates, idle, or trip sequence).
[FIX-M21] Live-position freshness: (a) /pushalarm now cross-feeds its
lat/lng into live_positions via the new shared
upsert_live_position() helper, time-guarded so older
timestamps can't rewind fresher fixes; (b) new
poll_stale_locations() runs every 10 min and calls
get_device_locations() for IMEIs whose live_positions.gps_time
is missing or > 30 min stale, recovering devices the 60s
sweep silently drops. Both the 60s sweep and
get_device_locations() now share the same time-guarded
upsert. _ensure_device ensure_device relocated to
ts_shared_rev for FK-guard reuse.
""" """
@ -82,7 +65,6 @@ from ts_shared_rev import (
clean_ts, clean_ts,
get_logger, get_logger,
ensure_device, ensure_device,
reverse_geocode,
safe_task, safe_task,
setup_shutdown, setup_shutdown,
upsert_live_position, upsert_live_position,
@ -238,7 +220,7 @@ def poll_live_positions():
gps_num = clean_int(p.get("gpsNum")) gps_num = clean_int(p.get("gpsNum"))
current_mileage = clean_num(p.get("currentMileage")) current_mileage = clean_num(p.get("currentMileage"))
# [FIX-M21] Time-guarded upsert via shared helper so the # [FIX-M20] Time-guarded upsert via shared helper so the
# 60s sweep, the alarm cross-feed, and get_device_locations # 60s sweep, the alarm cross-feed, and get_device_locations
# all agree about freshness ordering. The sweep is normally # all agree about freshness ordering. The sweep is normally
# the freshest source so the guard rarely rejects its writes. # the freshest source so the guard rarely rejects its writes.
@ -280,57 +262,6 @@ def poll_live_positions():
# ── 3. Trip Reports (Every 15m) ─────────────────────────────────────────────── # ── 3. Trip Reports (Every 15m) ───────────────────────────────────────────────
# [FIX-M20] Migration 09 added route_geom, start/end_address, vehicle_plate,
# waypoints_count to tracksolid.trips. poll_trips now enriches every poll-
# ingested trip from position_history (start/end fix + LineString polyline)
# and reverse-geocodes the endpoints, since jimi.device.track.mileage does
# not return coordinates. ON CONFLICT preserves webhook-supplied data when
# /pushtripreport later delivers native coords.
# Per-trip enrichment from position_history. Four readable scalar subqueries
# rather than a tighter CTE — runs sub-ms each given the (imei, gps_time) PK,
# and the readable form survives the edge case where start_time is just
# before the first available fix in the window (single CTE bounded by
# BETWEEN would return NULL there).
_ENRICH_QUERY = """
SELECT
(SELECT geom FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_geom,
(SELECT ST_Y(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_lat,
(SELECT ST_X(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time >= %s
ORDER BY gps_time ASC LIMIT 1) AS start_lng,
(SELECT geom FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_geom,
(SELECT ST_Y(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_lat,
(SELECT ST_X(geom) FROM tracksolid.position_history
WHERE imei = %s AND gps_time <= %s
ORDER BY gps_time DESC LIMIT 1) AS end_lng,
(SELECT ST_MakeLine(geom ORDER BY gps_time)
FROM tracksolid.position_history
WHERE imei = %s AND gps_time BETWEEN %s AND %s
AND geom IS NOT NULL) AS route_geom,
(SELECT COUNT(*) FROM tracksolid.position_history
WHERE imei = %s AND gps_time BETWEEN %s AND %s) AS waypoints_count
"""
def _load_plates_cache(cur) -> dict[str, str]:
"""Build {imei: vehicle_number} for active devices once per poll cycle."""
cur.execute("""
SELECT imei, vehicle_number
FROM tracksolid.devices
WHERE enabled_flag = 1 AND vehicle_number IS NOT NULL
""")
return {imei: plate for imei, plate in cur.fetchall()}
def poll_trips(): def poll_trips():
t0 = time.time() t0 = time.time()
token, imeis = get_token(), get_active_imeis() token, imeis = get_token(), get_active_imeis()
@ -342,8 +273,6 @@ def poll_trips():
with get_conn() as conn: with get_conn() as conn:
with conn.cursor() as cur: with conn.cursor() as cur:
plates = _load_plates_cache(cur)
for i in range(0, len(imeis), 50): for i in range(0, len(imeis), 50):
batch = imeis[i:i+50] batch = imeis[i:i+50]
resp = api_post("jimi.device.track.mileage", { resp = api_post("jimi.device.track.mileage", {
@ -362,67 +291,20 @@ def poll_trips():
# Divide by 1000 to store as distance_km. # Divide by 1000 to store as distance_km.
raw_dist = clean_num(t.get("distance")) raw_dist = clean_num(t.get("distance"))
dist_km = round(raw_dist / 1000.0, 4) if raw_dist is not None else None dist_km = round(raw_dist / 1000.0, 4) if raw_dist is not None else None
imei = t.get("imei")
trip_start = clean_ts(t.get("startTime"))
trip_end = clean_ts(t.get("endTime"))
idle_s = clean_int(t.get("idleSecond"))
# [FIX-M20] Enrich from position_history. trip_start/end
# may be None (rare malformed payload) — skip enrichment
# in that case so we still capture the row.
start_geom = end_geom = route_geom = None
start_lat = start_lng = end_lat = end_lng = None
waypoints_count = 0
if trip_start and trip_end:
cur.execute(_ENRICH_QUERY, (
imei, trip_start, # start_geom
imei, trip_start, # start_lat
imei, trip_start, # start_lng
imei, trip_end, # end_geom
imei, trip_end, # end_lat
imei, trip_end, # end_lng
imei, trip_start, trip_end, # route_geom
imei, trip_start, trip_end, # waypoints_count
))
(start_geom, start_lat, start_lng,
end_geom, end_lat, end_lng,
route_geom, waypoints_count) = cur.fetchone()
start_address = reverse_geocode(start_lat, start_lng)
end_address = reverse_geocode(end_lat, end_lng)
vehicle_plate = plates.get(imei)
cur.execute(""" cur.execute("""
INSERT INTO tracksolid.trips ( INSERT INTO tracksolid.trips (
imei, start_time, end_time, distance_km, imei, start_time, end_time, distance_km,
avg_speed_kmh, max_speed_kmh, driving_time_s, idle_time_s, avg_speed_kmh, max_speed_kmh, driving_time_s, source
start_geom, end_geom, route_geom, waypoints_count, ) VALUES (%s, %s, %s, %s, %s, %s, %s, 'poll')
start_address, end_address, vehicle_plate, source
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s,
%s, %s, %s, 'poll')
ON CONFLICT (imei, start_time) DO UPDATE SET ON CONFLICT (imei, start_time) DO UPDATE SET
end_time = EXCLUDED.end_time, end_time = EXCLUDED.end_time,
distance_km = EXCLUDED.distance_km, distance_km = EXCLUDED.distance_km,
max_speed_kmh = COALESCE(EXCLUDED.max_speed_kmh, tracksolid.trips.max_speed_kmh), max_speed_kmh = COALESCE(EXCLUDED.max_speed_kmh, tracksolid.trips.max_speed_kmh),
driving_time_s = COALESCE(EXCLUDED.driving_time_s, tracksolid.trips.driving_time_s), driving_time_s = COALESCE(EXCLUDED.driving_time_s, tracksolid.trips.driving_time_s)
idle_time_s = COALESCE(EXCLUDED.idle_time_s, tracksolid.trips.idle_time_s),
start_geom = COALESCE(tracksolid.trips.start_geom, EXCLUDED.start_geom),
end_geom = COALESCE(EXCLUDED.end_geom, tracksolid.trips.end_geom),
route_geom = COALESCE(EXCLUDED.route_geom, tracksolid.trips.route_geom),
waypoints_count = EXCLUDED.waypoints_count,
start_address = COALESCE(tracksolid.trips.start_address, EXCLUDED.start_address),
end_address = COALESCE(EXCLUDED.end_address, tracksolid.trips.end_address),
vehicle_plate = COALESCE(EXCLUDED.vehicle_plate, tracksolid.trips.vehicle_plate)
""", ( """, (
imei, trip_start, trip_end, dist_km, t.get("imei"), clean_ts(t.get("startTime")), clean_ts(t.get("endTime")),
clean_num(t.get("avgSpeed")), dist_km, clean_num(t.get("avgSpeed")),
clean_num(t.get("maxSpeed")), clean_num(t.get("maxSpeed")), clean_int(t.get("runTimeSecond"))
clean_int(t.get("runTimeSecond")),
idle_s,
start_geom, end_geom, route_geom, waypoints_count,
start_address, end_address, vehicle_plate,
)) ))
cur.execute("RELEASE SAVEPOINT sp") cur.execute("RELEASE SAVEPOINT sp")
inserted += cur.rowcount inserted += cur.rowcount
@ -631,7 +513,7 @@ def get_device_locations(imeis: list) -> int:
if not imei or not is_valid_fix(lat, lng): if not imei or not is_valid_fix(lat, lng):
continue continue
# [FIX-M21] FK guard — this path can see IMEIs the daily # [FIX-M20] FK guard — this path can see IMEIs the daily
# sync_devices hasn't picked up yet (especially when used # sync_devices hasn't picked up yet (especially when used
# as the stale-IMEI rescue path). # as the stale-IMEI rescue path).
ensure_device(cur, imei, clean(p.get("deviceName"))) ensure_device(cur, imei, clean(p.get("deviceName")))
@ -653,7 +535,7 @@ def get_device_locations(imeis: list) -> int:
# ── 7. Stale-IMEI Recovery — POLL-04 ───────────────────────────────────────── # ── 7. Stale-IMEI Recovery — POLL-04 ─────────────────────────────────────────
def poll_stale_locations(): def poll_stale_locations():
"""[FIX-M21] Refresh live_positions for IMEIs whose stored gps_time is """[FIX-M20] Refresh live_positions for IMEIs whose stored gps_time is
missing or older than 30 minutes. missing or older than 30 minutes.
Complements poll_live_positions (the 60s sweep), which silently omits Complements poll_live_positions (the 60s sweep), which silently omits
@ -687,7 +569,7 @@ def main():
schedule.every(15).minutes.do(safe_task(poll_trips, log)) schedule.every(15).minutes.do(safe_task(poll_trips, log))
schedule.every(15).minutes.do(safe_task(poll_parking, log)) schedule.every(15).minutes.do(safe_task(poll_parking, log))
schedule.every(30).minutes.do(safe_task(poll_track_list, log)) # [FIX-M14] schedule.every(30).minutes.do(safe_task(poll_track_list, log)) # [FIX-M14]
schedule.every(10).minutes.do(safe_task(poll_stale_locations, log)) # [FIX-M21] schedule.every(10).minutes.do(safe_task(poll_stale_locations, log)) # [FIX-M20]
schedule.every().day.at("02:00").do(safe_task(sync_devices, log)) schedule.every().day.at("02:00").do(safe_task(sync_devices, log))
while True: while True:

View file

@ -1,377 +0,0 @@
pgcli "postgres://postgres:U1pm3f5SX34DXkHoW6aKFsBHOlMA9binDPNG4aT0FAcg7AubEvYm0e6kU2dZiYrR@stage.rahamafresh.com:5433/tracksolid_db"
postgresql://postgres:U1pm3f5SX34DXkHoW6aKFsBHOlMA9binDPNG4aT0FAcg7AubEvYm0e6kU2dZiYrR@timescale_db-bo3nov2ija7g8wn9b1g2paxs-104717464280:5432/tracksolid_db
---- CURRENT LIVE POSITIONS ------- All devices with a position in the last hour ----
SELECT
d.device_name,
d.mc_type,
ROUND(lp.lat::numeric, 5) AS lat,
ROUND(lp.lng::numeric, 5) AS lng,
lp.speed,
lp.acc_status,
lp.gps_signal,
lp.gps_num AS satellites,
lp.gps_time AT TIME ZONE 'Africa/Nairobi' AS last_fix_eat,
ROUND(EXTRACT(EPOCH FROM (now() - lp.gps_time)) / 60.0, 0) AS mins_ago
FROM tracksolid.live_positions lp
JOIN tracksolid.devices d ON d.imei = lp.imei
WHERE lp.gps_time > now() - interval '1 hour'
ORDER BY lp.gps_time DESC;
----- All 19 live positions — current snapshot ----
SELECT
d.device_name,
d.mc_type,
ROUND(lp.lat::numeric, 5) AS lat,
ROUND(lp.lng::numeric, 5) AS lng,
lp.speed,
lp.acc_status,
lp.gps_time AT TIME ZONE 'Africa/Nairobi' AS last_fix_eat,
ROUND(EXTRACT(EPOCH FROM (now() - lp.gps_time)) / 3600.0, 1) AS hours_ago,
lp.current_mileage AS odometer_km
FROM tracksolid.live_positions lp
JOIN tracksolid.devices d ON d.imei = lp.imei
ORDER BY lp.gps_time DESC;
-------- Devices with no position (silent fleet) -----
SELECT d.imei, d.device_name, d.mc_type, d.sim, d.expiration::date
FROM tracksolid.devices d
LEFT JOIN tracksolid.live_positions lp ON lp.imei = d.imei
WHERE lp.imei IS NULL
ORDER BY d.mc_type, d.device_name;
---- Vehicles currently moving (ACC on OR speed > 0)
SELECT
d.device_name,
lp.speed,
lp.acc_status,
lp.gps_time AT TIME ZONE 'Africa/Nairobi' AS last_fix_eat
FROM tracksolid.live_positions lp
JOIN tracksolid.devices d ON d.imei = lp.imei
WHERE lp.speed > 0 OR lp.acc_status = '1'
ORDER BY lp.speed DESC;
---- Vehicles in Uganda -----
SELECT
d.device_name,
ROUND(lp.lat::numeric, 4) AS lat,
ROUND(lp.lng::numeric, 4) AS lng,
lp.gps_time AT TIME ZONE 'Africa/Nairobi' AS last_fix_eat
FROM tracksolid.live_positions lp
JOIN tracksolid.devices d ON d.imei = lp.imei
WHERE lp.lat NOT BETWEEN -5.0 AND 5.0
OR lp.lng NOT BETWEEN 33.9 AND 42.0;
---- Vehicles in Kenya -----
SELECT
d.device_name,
ROUND(lp.lat::numeric, 4) AS lat,
ROUND(lp.lng::numeric, 4) AS lng,
lp.gps_time AT TIME ZONE 'Africa/Nairobi' AS last_fix_eat
FROM tracksolid.live_positions lp
JOIN tracksolid.devices d ON d.imei = lp.imei
WHERE lp.lat BETWEEN -5.0 AND 5.0
OR lp.lng BETWEEN 33.9 AND 42.0;
========== TRIPS AND MOVEMENT ======
SELECT
d.device_name,
d.vehicle_number,
d.driver_name,
COUNT(*) AS trips,
ROUND(SUM(t.distance_km)::numeric, 2) AS total_km,
ROUND(AVG(t.avg_speed_kmh)::numeric, 1) AS avg_speed_kmh,
MAX(t.max_speed_kmh) AS top_speed_kmh,
ROUND(SUM(t.driving_time_s) / 3600.0, 2) AS drive_hours,
ROUND(SUM(t.idle_time_s) / 3600.0, 2) AS idle_hours,
MIN(t.start_time AT TIME ZONE 'Africa/Nairobi') AS day_start,
MAX(t.end_time AT TIME ZONE 'Africa/Nairobi') AS day_end
FROM tracksolid.trips t
JOIN tracksolid.devices d ON d.imei = t.imei
WHERE t.start_time >= CURRENT_DATE AT TIME ZONE 'Africa/Nairobi'
GROUP BY d.device_name, d.vehicle_number, d.driver_name
ORDER BY total_km DESC;
------ trips summary LAST 24 HOURS per vehicle -------
SELECT
d.device_name,
t.start_time AT TIME ZONE 'Africa/Nairobi' AS start_eat,
t.end_time AT TIME ZONE 'Africa/Nairobi' AS end_eat,
ROUND(t.distance_km::numeric / 1000.0, 2) AS distance_km,
t.avg_speed_kmh,
t.max_speed_kmh,
ROUND(t.driving_time_s / 60.0, 0) AS drive_mins,
ROUND(t.idle_time_s / 60.0, 0) AS idle_mins,
t.source
FROM tracksolid.trips t
JOIN tracksolid.devices d ON d.imei = t.imei
WHERE t.start_time > now() - interval '24 hours'
ORDER BY t.start_time DESC;
------- Fleet utilisation rate per vehicle (today)
SELECT
d.device_name,
d.driver_name,
ROUND(SUM(t.driving_time_s) / 3600.0, 2) AS drive_hours,
ROUND(SUM(t.idle_time_s) / 3600.0, 2) AS idle_hours,
LEAST(ROUND(SUM(t.driving_time_s + COALESCE(t.idle_time_s, 0)) / (12.0 * 3600) * 100, 1), 100) AS utilisation_pct
FROM tracksolid.trips t
JOIN tracksolid.devices d ON d.imei = t.imei
WHERE t.start_time >= CURRENT_DATE AT TIME ZONE 'Africa/Nairobi'
GROUP BY d.device_name, d.driver_name
ORDER BY utilisation_pct DESC;
KDK 829A GP | | 1.87 | | 15.5
FRED KMGW 538W HULETI | | 1.65 | | 13.7
X3-63282 | | 1.25 | | 10.4
-----Tracking to this point of the day ----
SELECT
d.device_name,
d.driver_name,
ROUND(SUM(t.driving_time_s) / 3600.0, 2) AS drive_hours,
ROUND(SUM(t.idle_time_s) / 3600.0, 2) AS idle_hours,
LEAST(ROUND(
SUM(t.driving_time_s + COALESCE(t.idle_time_s, 0))
/ (EXTRACT(EPOCH FROM (
LEAST(now(), CURRENT_DATE::timestamp AT TIME ZONE 'Africa/Nairobi' + interval '19 hours 30 minutes')
- (CURRENT_DATE::timestamp AT TIME ZONE 'Africa/Nairobi' + interval '7 hours 30 minutes')
))) * 100
, 1), 100) AS utilisation_pct_so_far
FROM tracksolid.trips t
JOIN tracksolid.devices d ON d.imei = t.imei
WHERE t.start_time >= (CURRENT_DATE::timestamp AT TIME ZONE 'Africa/Nairobi' + interval '7 hours 30 minutes')
GROUP BY d.device_name, d.driver_name
ORDER BY utilisation_pct_so_far DESC;
------ Vehicles that have not moved today -------
SELECT d.device_name, d.mc_type, d.driver_name
FROM tracksolid.devices d
LEFT JOIN tracksolid.trips t
ON t.imei = d.imei
AND t.start_time >= CURRENT_DATE AT TIME ZONE 'Africa/Nairobi'
WHERE t.imei IS NULL
ORDER BY d.device_name;
------ Distance per driver — last 30 days
SELECT
d.device_name,
d.driver_name,
COUNT(DISTINCT DATE(t.start_time AT TIME ZONE 'Africa/Nairobi')) AS active_days,
COUNT(*) AS total_trips,
ROUND(SUM(t.distance_km / 1000.0)::numeric, 0) AS total_km,
ROUND(AVG(t.distance_km / 1000.0)::numeric, 1) AS avg_km_per_trip,
MAX(t.max_speed_kmh) AS top_speed_ever
FROM tracksolid.trips t
JOIN tracksolid.devices d ON d.imei = t.imei
WHERE t.start_time > now() - interval '30 days'
GROUP BY d.device_name, d.driver_name
ORDER BY total_km DESC;
====== ALL ALARMS =====
----Alarms in 24 hours ----
SELECT
d.device_name,
a.alarm_type,
a.alarm_name,
a.alarm_time AT TIME ZONE 'Africa/Nairobi' AS alarm_time_eat,
ROUND(a.lat::numeric, 5) AS lat,
ROUND(a.lng::numeric, 5) AS lng,
a.speed,
a.severity,
a.acknowledged_at
FROM tracksolid.alarms a
JOIN tracksolid.devices d ON d.imei = a.imei
WHERE a.alarm_time > now() - interval '24 hours'
ORDER BY a.alarm_time DESC;
----Alarms in 7 Days ----
SELECT
a.alarm_name,
a.alarm_type,
COUNT(*) AS occurrences,
COUNT(DISTINCT a.imei) AS devices_affected,
MAX(a.alarm_time AT TIME ZONE 'Africa/Nairobi') AS last_seen_eat
FROM tracksolid.alarms a
WHERE a.alarm_time > now() - interval '7 days'
GROUP BY a.alarm_name, a.alarm_type
ORDER BY occurrences DESC;
------ unacknowledged alarms ------
SELECT
d.device_name,
a.alarm_name,
a.alarm_time AT TIME ZONE 'Africa/Nairobi' AS alarm_time_eat,
ROUND(EXTRACT(EPOCH FROM (now() - a.alarm_time)) / 3600.0, 1) AS hours_open
FROM tracksolid.alarms a
JOIN tracksolid.devices d ON d.imei = a.imei
WHERE a.acknowledged_at IS NULL
ORDER BY a.alarm_time DESC;
------ acknowledged alarms ------
UPDATE tracksolid.alarms
SET acknowledged_at = now(),
acknowledged_by = 'operator_name'
WHERE id = <alarm_id>;
===========
------ Position history by source — counts ----
SELECT
source,
COUNT(*) AS fixes,
MIN(gps_time AT TIME ZONE 'Africa/Nairobi') AS earliest,
MAX(gps_time AT TIME ZONE 'Africa/Nairobi') AS latest
FROM tracksolid.position_history
GROUP BY source;
--------- Route replay for a specific vehicle — last 24 hours
device = name <'FRED KMGW 538W HULETI'>
SELECT
ph.gps_time AT TIME ZONE 'Africa/Nairobi' AS gps_time_eat,
ROUND(ph.lat::numeric, 5) AS lat,
ROUND(ph.lng::numeric, 5) AS lng,
ph.speed,
ph.direction,
ph.acc_status,
ph.source
FROM tracksolid.position_history ph
JOIN tracksolid.devices d ON d.imei = ph.imei
WHERE d.device_name = <'FRED KMGW 538W HULETI'>
AND ph.gps_time > now() - interval '24 hours'
ORDER BY ph.gps_time ASC;
-------- Fix density per device — last 24 hours ---------
SELECT
d.device_name,
COUNT(*) AS total_fixes,
COUNT(*) FILTER (WHERE ph.source = 'poll') AS poll_fixes,
COUNT(*) FILTER (WHERE ph.source = 'track_list') AS track_list_fixes,
MIN(ph.gps_time AT TIME ZONE 'Africa/Nairobi') AS first_fix,
MAX(ph.gps_time AT TIME ZONE 'Africa/Nairobi') AS last_fix
FROM tracksolid.position_history ph
JOIN tracksolid.devices d ON d.imei = ph.imei
WHERE ph.gps_time > now() - interval '24 hours'
GROUP BY d.device_name
ORDER BY total_fixes DESC;
### Device & Fleet Registry
-------- Full fleet — all 63 devices ------
SELECT
device_name,
mc_type,
vehicle_number,
driver_name,
sim,
ROUND(current_mileage_km::numeric, 0) AS odometer_km,
expiration::date AS expires,
enabled_flag
FROM tracksolid.devices
ORDER BY mc_type, device_name;
-------- Fleet by devices model ------
SELECT mc_type, COUNT(*) AS devices
FROM tracksolid.devices
GROUP BY mc_type ORDER BY devices DESC;
------ fleet by odometer readings -----
SELECT
device_name,
mc_type,
sim,
ROUND(current_mileage_km::numeric, 0) AS odometer_km,
expiration::date AS expires
FROM tracksolid.devices
WHERE current_mileage_km IS NOT NULL AND current_mileage_km > 0
ORDER BY current_mileage_km DESC
LIMIT 15;
---- fleet blank driver sim vehicle number blanks ----
SELECT device_name, mc_type, sim
FROM tracksolid.devices
WHERE vehicle_number IS NULL OR vehicle_number = ''
OR driver_name IS NULL OR driver_name = ''
ORDER BY mc_type, device_name;
----- fleet by expiry dates ---
SELECT
COUNT(*) FILTER (WHERE expiration IS NULL) AS no_expiry_set,
COUNT(*) FILTER (WHERE expiration < now()) AS already_expired,
COUNT(*) FILTER (WHERE expiration BETWEEN now() AND now() + interval '90 days') AS expiring_90days,
COUNT(*) FILTER (WHERE expiration > now() + interval '90 days') AS valid_long_term
FROM tracksolid.devices;
-----no of rows in db -----
SELECT
(SELECT COUNT(*) FROM tracksolid.devices) AS devices,
(SELECT COUNT(*) FROM tracksolid.live_positions) AS live_positions,
(SELECT COUNT(*) FROM tracksolid.position_history) AS position_history,
(SELECT COUNT(*) FROM tracksolid.trips) AS trips,
(SELECT COUNT(*) FROM tracksolid.alarms) AS alarms,
(SELECT COUNT(*) FROM tracksolid.parking_events) AS parking_events,
(SELECT COUNT(*) FROM tracksolid.obd_readings) AS obd_readings,
(SELECT COUNT(*) FROM tracksolid.device_events) AS device_events,
(SELECT COUNT(*) FROM tracksolid.fuel_readings) AS fuel_readings,
(SELECT COUNT(*) FROM tracksolid.temperature_readings) AS temperature_readings,
(SELECT COUNT(*) FROM tracksolid.lbs_readings) AS lbs_readings,
(SELECT COUNT(*) FROM tracksolid.ingestion_log) AS ingestion_log;
=====
SELECT 'devices' AS table_name, COUNT(*) FROM tracksolid.devices
UNION ALL
SELECT 'live_positions', COUNT(*) FROM tracksolid.live_positions
UNION ALL
SELECT 'position_history', COUNT(*) FROM tracksolid.position_history
UNION ALL
SELECT 'trips', COUNT(*) FROM tracksolid.trips
UNION ALL
SELECT 'alarms', COUNT(*) FROM tracksolid.alarms
UNION ALL
SELECT 'parking_events', COUNT(*) FROM tracksolid.parking_events
UNION ALL
SELECT 'obd_readings', COUNT(*) FROM tracksolid.obd_readings
UNION ALL
SELECT 'device_events', COUNT(*) FROM tracksolid.device_events
UNION ALL
SELECT 'fuel_readings', COUNT(*) FROM tracksolid.fuel_readings
UNION ALL
SELECT 'temperature_readings', COUNT(*) FROM tracksolid.temperature_readings
UNION ALL
SELECT 'lbs_readings', COUNT(*) FROM tracksolid.lbs_readings
UNION ALL
SELECT 'ingestion_log', COUNT(*) FROM tracksolid.ingestion_log
ORDER BY table_name;

View file

@ -1,297 +0,0 @@
#!/usr/bin/env python3
"""
Tracksolid Pro - Device List Extractor
Calls jimi.user.device.list and saves all vehicle/device data to CSV and JSON.
Uses the same signing approach as tracksolid_update.py (confirmed working):
- POST as x-www-form-urlencoded
- All parameter values cast to strings before signing
Usage:
python3 tracksolid_extract.py
python3 tracksolid_extract.py --target "Fireside Communications"
python3 tracksolid_extract.py --format json
python3 tracksolid_extract.py --format both
Environment variables (same .env file as tracksolid_update.py):
TS_USER_ID - Your Tracksolid account username
TS_USER_PWD_MD5 - MD5 hash of your password (lowercase)
TS_APP_KEY - Your appKey from JIMI
TS_APP_SECRET - Your appSecret from JIMI
TS_API_URL - API base URL (defaults to EU node)
TS_TARGET - Account to query (defaults to TS_USER_ID)
"""
import hashlib
import os
import sys
import json
import logging
import argparse
import time
from datetime import datetime, timezone
from pathlib import Path
import requests
import pandas as pd
# ──────────────────────────────────────────────────────────────────────────────
# CONFIGURATION — reads from environment / same .env as the updater
# ──────────────────────────────────────────────────────────────────────────────
CONFIG = {
"user_id": os.getenv("TS_USER_ID", "Fireside Communications"),
"user_pwd_md5": os.getenv("TS_USER_PWD_MD5", "81a1b005efd3596073e38efd8a2fd3fd"),
"app_key": os.getenv("TS_APP_KEY", "8FB345B8693CCD00BB70D528C0D4019E"),
"app_secret": os.getenv("TS_APP_SECRET", "3177c89993b446c6aced0d7c56375d2c"),
"api_url": os.getenv("TS_API_URL", "https://eu-open.tracksolidpro.com/route/rest"),
"target": os.getenv("TS_TARGET", ""), # account to query; defaults to user_id
"expires_in": "7200",
}
# ──────────────────────────────────────────────────────────────────────────────
# LOGGING
# ──────────────────────────────────────────────────────────────────────────────
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler("tracksolid_extract.log", encoding="utf-8"),
],
)
log = logging.getLogger(__name__)
# ──────────────────────────────────────────────────────────────────────────────
# SIGNING UTILITIES (identical to tracksolid_update.py)
# ──────────────────────────────────────────────────────────────────────────────
def utc_timestamp() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
def build_sign(params: dict, app_secret: str) -> str:
sorted_keys = sorted(
k for k in params
if k != "sign" and params[k] is not None and str(params[k]).strip() != ""
)
param_string = "".join(f"{k}{params[k]}" for k in sorted_keys)
raw_string = f"{app_secret}{param_string}{app_secret}"
return hashlib.md5(raw_string.encode("utf-8")).hexdigest().upper()
# ──────────────────────────────────────────────────────────────────────────────
# TRACKSOLID CLIENT
# ──────────────────────────────────────────────────────────────────────────────
class TracksolidClient:
def __init__(self, cfg: dict):
self.cfg = cfg
self._token: str | None = None
self._token_expires_at: float = 0.0
self.session = requests.Session()
def _post(self, params: dict) -> dict:
str_params = {
k: str(v)
for k, v in params.items()
if v is not None and str(v).strip() != ""
}
str_params["sign"] = build_sign(str_params, self.cfg["app_secret"])
log.debug("POST %s params=%s", self.cfg["api_url"], str_params)
resp = self.session.post(
self.cfg["api_url"],
data=str_params, # form-encoded — confirmed working
timeout=30,
)
resp.raise_for_status()
data = resp.json()
log.debug("Response: %s", json.dumps(data))
return data
def _common_params(self, method: str) -> dict:
return {
"method": method,
"timestamp": utc_timestamp(),
"app_key": self.cfg["app_key"],
"sign_method": "md5",
"v": "1.0",
"format": "json",
}
def get_token(self) -> str:
if self._token and time.time() < self._token_expires_at - 60:
return self._token
log.info("Obtaining access token ...")
params = self._common_params("jimi.oauth.token.get")
params.update({
"user_id": self.cfg["user_id"],
"user_pwd_md5": self.cfg["user_pwd_md5"],
"expires_in": self.cfg["expires_in"],
})
data = self._post(params)
if data.get("code") != 0:
raise RuntimeError(
f"Auth failed — code={data.get('code')} message={data.get('message')}"
)
self._token = data["result"]["accessToken"]
self._token_expires_at = time.time() + int(data["result"]["expiresIn"])
log.info("Token acquired. Valid for %s seconds.", data["result"]["expiresIn"])
return self._token
def get_device_list(self, target: str) -> list[dict]:
"""
Call jimi.user.device.list for the given target account.
Returns the full list of device/vehicle records.
"""
log.info("Fetching device list for account: %s", target)
token = self.get_token()
params = self._common_params("jimi.user.device.list")
params["access_token"] = token
params["target"] = target
data = self._post(params)
if data.get("code") != 0:
raise RuntimeError(
f"Device list failed — code={data.get('code')} message={data.get('message')}"
)
devices = data.get("result", [])
log.info("Retrieved %d devices.", len(devices))
return devices
# ──────────────────────────────────────────────────────────────────────────────
# OUTPUT HELPERS
# ──────────────────────────────────────────────────────────────────────────────
# Friendly column names for the CSV output
COLUMN_RENAME = {
"imei": "IMEI",
"deviceName": "Device Name",
"mcType": "Model",
"mcTypeUseScope": "Vehicle Type",
"sim": "SIM",
"expiration": "Platform Expiry",
"activationTime": "Activated",
"reMark": "Remarks",
"vehicleName": "Vehicle Name",
"vehicleIcon": "Icon",
"vehicleNumber": "License Plate",
"vehicleModels": "Vehicle Model",
"carFrame": "VIN",
"driverName": "Driver Name",
"driverPhone": "Driver Phone",
"enabledFlag": "Active",
"engineNumber": "Engine Number",
"deviceGroupId": "Group ID",
"deviceGroup": "Group",
}
def save_csv(devices: list[dict], path: str):
df = pd.DataFrame(devices)
df.rename(columns=COLUMN_RENAME, inplace=True)
# Put the most useful columns first
priority = ["IMEI", "License Plate", "Driver Name", "Driver Phone",
"Device Name", "Vehicle Model", "Vehicle Type", "Group",
"SIM", "Platform Expiry", "Activated", "Active",
"VIN", "Engine Number", "Remarks"]
ordered = [c for c in priority if c in df.columns]
rest = [c for c in df.columns if c not in ordered]
df = df[ordered + rest]
df.to_csv(path, index=False)
log.info("CSV saved → %s (%d rows, %d columns)", path, len(df), len(df.columns))
def save_json(devices: list[dict], path: str):
with open(path, "w", encoding="utf-8") as f:
json.dump(devices, f, indent=2, ensure_ascii=False)
log.info("JSON saved → %s (%d records)", path, len(devices))
def print_summary(devices: list[dict]):
df = pd.DataFrame(devices)
total = len(df)
active = df["enabledFlag"].eq(1).sum() if "enabledFlag" in df.columns else "?"
groups = df["deviceGroup"].nunique() if "deviceGroup" in df.columns else "?"
with_plate = df["vehicleNumber"].notna().sum() if "vehicleNumber" in df.columns else "?"
with_driver = df["driverName"].notna().sum() if "driverName" in df.columns else "?"
print()
print("=" * 50)
print(" DEVICE LIST SUMMARY")
print("=" * 50)
print(f" Total devices : {total}")
print(f" Active : {active}")
print(f" Device groups : {groups}")
print(f" With plate no. : {with_plate}")
print(f" With driver name : {with_driver}")
print("=" * 50)
if "deviceGroup" in df.columns:
print("\n Breakdown by group:")
for group, count in df["deviceGroup"].value_counts().items():
print(f" {group:<25} {count} devices")
print()
# ──────────────────────────────────────────────────────────────────────────────
# MAIN
# ──────────────────────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser(
description="Extract Tracksolid device list to CSV / JSON."
)
parser.add_argument(
"--target", default="",
help="Account to query (default: same as TS_USER_ID / user_id in CONFIG)."
)
parser.add_argument(
"--format", choices=["csv", "json", "both"], default="csv",
help="Output format (default: csv)."
)
parser.add_argument(
"--out", default="",
help="Output filename without extension (default: tracksolid_devices_YYYYMMDD_HHMMSS)."
)
args = parser.parse_args()
# Resolve target account
target = args.target or CONFIG["target"] or CONFIG["user_id"]
# Resolve output filename base
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
out_base = args.out or f"tracksolid_devices_{timestamp}"
# ── Fetch ──────────────────────────────────────────────────────────────────
client = TracksolidClient(CONFIG)
try:
devices = client.get_device_list(target)
except Exception as exc:
log.error("Failed to fetch device list: %s", exc)
sys.exit(1)
if not devices:
log.warning("No devices returned for account: %s", target)
sys.exit(0)
# ── Save ───────────────────────────────────────────────────────────────────
if args.format in ("csv", "both"):
save_csv(devices, f"{out_base}.csv")
if args.format in ("json", "both"):
save_json(devices, f"{out_base}.json")
# ── Summary ────────────────────────────────────────────────────────────────
print_summary(devices)
if __name__ == "__main__":
main()

View file

@ -1,56 +0,0 @@
### Pipeline health — last hour (key check)
SELECT
endpoint,
COUNT(*) AS calls,
SUM(rows_upserted) AS upserted,
SUM(rows_inserted) AS inserted,
ROUND(AVG(duration_ms)::numeric, 0) AS avg_ms,
COUNT(*) FILTER (WHERE success = false) AS failures,
MAX(run_at AT TIME ZONE 'Africa/Nairobi') AS last_call_eat
FROM tracksolid.ingestion_log
WHERE run_at > now() - interval '1 hour'
GROUP BY endpoint
ORDER BY calls DESC;
-------- Ingestion Pipeline Health
SELECT
endpoint,
COUNT(*) AS total_calls,
SUM(rows_upserted) AS total_upserted,
SUM(rows_inserted) AS total_inserted,
ROUND(AVG(duration_ms)::numeric, 0) AS avg_ms,
COUNT(*) FILTER (WHERE success = false) AS failures,
MIN(run_at AT TIME ZONE 'Africa/Nairobi') AS first_call,
MAX(run_at AT TIME ZONE 'Africa/Nairobi') AS last_call
FROM tracksolid.ingestion_log
GROUP BY endpoint
ORDER BY total_calls DESC;
### Recent calls — last 20 entries
SELECT
run_at AT TIME ZONE 'Africa/Nairobi' AS run_eat,
endpoint,
imei_count,
rows_upserted,
rows_inserted,
duration_ms,
success,
error_message
FROM tracksolid.ingestion_log
ORDER BY run_at DESC
LIMIT 20;
### Recent calls — FAILED CALLS entries
SELECT
run_at AT TIME ZONE 'Africa/Nairobi' AS run_eat,
endpoint,
error_code,
error_message
FROM tracksolid.ingestion_log
WHERE success = false
ORDER BY run_at DESC;

View file

@ -1,359 +0,0 @@
#!/usr/bin/env python3
"""
Tracksolid Pro - Bulk Vehicle Information Updater
Updates vehicle details via the jimi.open.device.update API endpoint
using data from the Fireside logistics CSV.
Signing approach taken directly from tspostman.py (confirmed working):
- POST as x-www-form-urlencoded (NOT JSON)
- All parameter values cast to strings before signing
- expires_in passed as string '7200', not integer
Usage:
python tracksolid_update.py [--dry-run] [--csv path/to/file.csv] [--limit N]
Environment variables (or edit CONFIG below):
TS_USER_ID - Your Tracksolid account username
TS_USER_PWD_MD5 - MD5 hash of your password (lowercase)
TS_APP_KEY - Your appKey from JIMI
TS_APP_SECRET - Your appSecret from JIMI
TS_API_URL - API base URL (defaults to EU node)
TS_CSV_PATH - Path to the logistics CSV
"""
import hashlib
import time
import json
import logging
import argparse
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
import requests
import pandas as pd
# ──────────────────────────────────────────────────────────────────────────────
# CONFIGURATION — edit here or set environment variables
# ──────────────────────────────────────────────────────────────────────────────
CONFIG = {
"user_id": os.getenv("TS_USER_ID", "Fireside Communications"),
"user_pwd_md5": os.getenv("TS_USER_PWD_MD5", "81a1b005efd3596073e38efd8a2fd3fd"),
"app_key": os.getenv("TS_APP_KEY", "8FB345B8693CCD00BB70D528C0D4019E"),
"app_secret": os.getenv("TS_APP_SECRET", "3177c89993b446c6aced0d7c56375d2c"),
# EU node confirmed for this account
"api_url": os.getenv("TS_API_URL", "https://eu-open.tracksolidpro.com/route/rest"),
"expires_in": "7200", # string, not int — matches tspostman.py
"request_delay": 0.5, # seconds between API calls
}
CSV_PATH = os.getenv("TS_CSV_PATH", "20260414_FS__Logistics_-_final_fixed.csv")
# ──────────────────────────────────────────────────────────────────────────────
# LOGGING
# ──────────────────────────────────────────────────────────────────────────────
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler("tracksolid_update.log", encoding="utf-8"),
],
)
log = logging.getLogger(__name__)
# ──────────────────────────────────────────────────────────────────────────────
# SIGNING UTILITIES (ported directly from tspostman.py)
# ──────────────────────────────────────────────────────────────────────────────
def utc_timestamp() -> str:
"""UTC time formatted as yyyy-MM-dd HH:mm:ss."""
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
def build_sign(params: dict, app_secret: str) -> str:
"""
Tracksolid signing algorithm (matches tspostman.py exactly):
1. Sort all param keys alphabetically, exclude 'sign' and empty values.
2. Concatenate key+value pairs with no separators.
3. Wrap with appSecret on both sides.
4. MD5 -> UPPERCASE 32-char string.
All values must already be strings before calling this.
"""
sorted_keys = sorted(
k for k in params
if k != "sign" and params[k] is not None and str(params[k]).strip() != ""
)
param_string = "".join(f"{k}{params[k]}" for k in sorted_keys)
raw_string = f"{app_secret}{param_string}{app_secret}"
return hashlib.md5(raw_string.encode("utf-8")).hexdigest().upper()
# ──────────────────────────────────────────────────────────────────────────────
# TRACKSOLID CLIENT
# ──────────────────────────────────────────────────────────────────────────────
class TracksolidClient:
def __init__(self, cfg: dict):
self.cfg = cfg
self._token: str | None = None
self._token_expires_at: float = 0.0
self.session = requests.Session()
# No Content-Type set here — requests sets it automatically to
# application/x-www-form-urlencoded when data= is used (matching tspostman.py)
def _post(self, params: dict) -> dict:
"""
Sign and POST params using x-www-form-urlencoded encoding.
Confirmed working approach from tspostman.py:
- Cast all values to strings
- Use data= (form-encoded), NOT json=
"""
str_params = {
k: str(v)
for k, v in params.items()
if v is not None and str(v).strip() != ""
}
str_params["sign"] = build_sign(str_params, self.cfg["app_secret"])
log.debug("POST %s params=%s", self.cfg["api_url"], str_params)
resp = self.session.post(
self.cfg["api_url"],
data=str_params, # form-encoded, NOT json=
timeout=30,
)
resp.raise_for_status()
data = resp.json()
log.debug("Response: %s", json.dumps(data))
return data
def _common_params(self, method: str) -> dict:
return {
"method": method,
"timestamp": utc_timestamp(),
"app_key": self.cfg["app_key"],
"sign_method": "md5",
"v": "1.0",
"format": "json",
}
def get_token(self) -> str:
"""Return a valid access token, fetching a new one only when needed."""
if self._token and time.time() < self._token_expires_at - 60:
log.debug("Reusing cached token.")
return self._token
log.info("Obtaining new access token ...")
params = self._common_params("jimi.oauth.token.get")
params.update({
"user_id": self.cfg["user_id"],
"user_pwd_md5": self.cfg["user_pwd_md5"],
"expires_in": self.cfg["expires_in"], # already a string per tspostman.py
})
data = self._post(params)
if data.get("code") != 0:
raise RuntimeError(
f"Auth failed — code={data.get('code')} message={data.get('message')}"
)
self._token = data["result"]["accessToken"]
self._token_expires_at = time.time() + int(data["result"]["expiresIn"])
log.info("Token acquired. Valid for %s seconds.", data["result"]["expiresIn"])
return self._token
def update_vehicle(self, imei: str, fields: dict, dry_run: bool = False) -> dict:
"""
Call jimi.open.device.update for one IMEI.
fields: dict using local key names (see row_to_fields below).
Returns the API response dict.
"""
if dry_run:
log.info("[DRY-RUN] IMEI %s -> %s", imei, fields)
return {"code": 0, "message": "dry-run"}
token = self.get_token()
params = self._common_params("jimi.open.device.update")
params["access_token"] = token
params["imei"] = str(imei)
# Map local field names -> Tracksolid API field names
api_field_map = {
"license_plate": "vehicle_number",
"vehicle_name": "vehicle_name",
"vehicle_icon": "vehicle_icon",
"driver_name": "driver_name",
"driver_phone": "driver_phone",
"vehicle_model": "vehicle_models",
"vin": "carFrame",
"engine_number": "engineNumber",
"device_name": "device_name",
"fuel_per_100": "oilWear",
"sim": "sim",
"remarks": "remarks",
}
for local_key, api_key in api_field_map.items():
val = fields.get(local_key)
if val:
params[api_key] = str(val)
return self._post(params)
# ──────────────────────────────────────────────────────────────────────────────
# CSV PARSING
# ──────────────────────────────────────────────────────────────────────────────
def clean(val) -> str | None:
"""Return None for NaN/empty values, else a stripped string."""
if pd.isna(val) or str(val).strip() in ("", "nan", "NaN"):
return None
s = str(val).strip()
if s.endswith(".0") and s[:-2].lstrip("+-").isdigit():
s = s[:-2]
return s
def row_to_fields(row: pd.Series) -> dict:
"""Map one CSV row to local field names used by update_vehicle()."""
return {
"device_name": clean(row.get("device_name")),
"vehicle_name": clean(row.get("vehicle_name")),
"vehicle_icon": clean(row.get("vehicle_icon")),
"license_plate": clean(row.get("vehicle_number")),
"vehicle_model": clean(row.get("vehicle_models")),
"driver_name": clean(row.get("driver_name")),
"driver_phone": clean(row.get("driver_phone")),
"sim": clean(row.get("sim")),
"vin": clean(row.get("vin")),
"engine_number": clean(row.get("engine_number")),
"fuel_per_100": clean(row.get("fuel_100km")),
"remarks": clean(row.get("remarks")),
}
# ──────────────────────────────────────────────────────────────────────────────
# MAIN
# ──────────────────────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser(
description="Bulk-update Tracksolid vehicle info from CSV."
)
parser.add_argument(
"--dry-run", action="store_true",
help="Show what would be sent without making update API calls."
)
parser.add_argument(
"--csv", default=CSV_PATH,
help=f"Path to the logistics CSV (default: {CSV_PATH})"
)
parser.add_argument(
"--limit", type=int, default=None,
help="Only process the first N rows (useful for testing)."
)
args = parser.parse_args()
# ── Load CSV ───────────────────────────────────────────────────────────────
csv_file = Path(args.csv)
if not csv_file.exists():
log.error("CSV file not found: %s", csv_file)
sys.exit(1)
df = pd.read_csv(csv_file, dtype={"imei": str})
log.info("Loaded %d rows from %s", len(df), csv_file)
if args.limit:
df = df.head(args.limit)
log.info("Limiting to first %d rows.", args.limit)
df = df[df["imei"].notna() & (df["imei"].str.strip() != "")]
log.info("%d rows have a valid IMEI.", len(df))
if df.empty:
log.warning("No rows to process. Exiting.")
sys.exit(0)
# ── Initialise client & verify auth ───────────────────────────────────────
client = TracksolidClient(CONFIG)
if not args.dry_run:
try:
client.get_token()
except Exception as exc:
log.error("Authentication failed: %s", exc)
log.error("Check TS_USER_ID, TS_USER_PWD_MD5, TS_APP_KEY, TS_APP_SECRET.")
sys.exit(1)
# ── Process rows ───────────────────────────────────────────────────────────
results = []
success = 0
failed = 0
skipped = 0
for idx, row in df.iterrows():
imei = str(row["imei"]).strip()
fields = row_to_fields(row)
# Skip rows where every updatable field is empty
if not any(fields.values()):
log.warning("Row %d (IMEI %s): no updatable fields, skipping.", idx + 1, imei)
skipped += 1
continue
log.info(
"Row %d/%d — IMEI: %s | Plate: %s | Driver: %s",
idx + 1, len(df), imei,
fields.get("license_plate") or "",
fields.get("driver_name") or "",
)
try:
resp = client.update_vehicle(imei, fields, dry_run=args.dry_run)
if resp.get("code") == 0:
log.info(" OK")
success += 1
else:
log.warning(
" API error — code=%s message=%s",
resp.get("code"), resp.get("message")
)
failed += 1
results.append({
"imei": imei,
**fields,
"api_code": resp.get("code"),
"api_message": resp.get("message"),
})
except Exception as exc:
log.error(" Exception for IMEI %s: %s", imei, exc)
failed += 1
results.append({
"imei": imei,
**fields,
"api_code": "EXCEPTION",
"api_message": str(exc),
})
if not args.dry_run:
time.sleep(CONFIG["request_delay"])
# ── Summary & audit CSV ───────────────────────────────────────────────────
log.info("-" * 60)
log.info(
"Done. OK: %d Failed: %d Skipped: %d | Total: %d",
success, failed, skipped, success + failed + skipped
)
out_path = "tracksolid_update_results.csv"
pd.DataFrame(results).to_csv(out_path, index=False)
log.info("Audit results written to %s", out_path)
if __name__ == "__main__":
main()

View file

@ -1,348 +0,0 @@
#!/usr/bin/env python3
"""
Tracksolid Pro - Bulk Vehicle Information Updater
Updates vehicle details via the jimi.open.device.update API endpoint
using data from the Fireside logistics CSV.
Signing approach taken directly from tspostman.py (confirmed working):
- POST as x-www-form-urlencoded (NOT JSON)
- All parameter values cast to strings before signing
- expires_in passed as string '7200', not integer
Usage:
python tracksolid_update.py [--dry-run] [--csv path/to/file.csv] [--limit N]
Environment variables (or edit CONFIG below):
TS_USER_ID - Your Tracksolid account username
TS_USER_PWD_MD5 - MD5 hash of your password (lowercase)
TS_APP_KEY - Your appKey from JIMI
TS_APP_SECRET - Your appSecret from JIMI
TS_API_URL - API base URL (defaults to EU node)
TS_CSV_PATH - Path to the logistics CSV
"""
import hashlib
import time
import json
import logging
import argparse
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
import requests
import pandas as pd
# ──────────────────────────────────────────────────────────────────────────────
# CONFIGURATION — edit here or set environment variables
# ──────────────────────────────────────────────────────────────────────────────
CONFIG = {
"user_id": os.getenv("TS_USER_ID", "Fireside Communications"),
"user_pwd_md5": os.getenv("TS_USER_PWD_MD5", "81a1b005efd3596073e38efd8a2fd3fd"),
"app_key": os.getenv("TS_APP_KEY", "8FB345B8693CCD00BB70D528C0D4019E"),
"app_secret": os.getenv("TS_APP_SECRET", "3177c89993b446c6aced0d7c56375d2c"),
# EU node confirmed for this account
"api_url": os.getenv("TS_API_URL", "https://eu-open.tracksolidpro.com/route/rest"),
"expires_in": "7200", # string, not int — matches tspostman.py
"request_delay": 0.5, # seconds between API calls
}
CSV_PATH = os.getenv("TS_CSV_PATH", "20260414_FS__Logistics_-_final_fixed.csv")
# ──────────────────────────────────────────────────────────────────────────────
# LOGGING
# ──────────────────────────────────────────────────────────────────────────────
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler("tracksolid_update.log", encoding="utf-8"),
],
)
log = logging.getLogger(__name__)
# ──────────────────────────────────────────────────────────────────────────────
# SIGNING UTILITIES (ported directly from tspostman.py)
# ──────────────────────────────────────────────────────────────────────────────
def utc_timestamp() -> str:
"""UTC time formatted as yyyy-MM-dd HH:mm:ss."""
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
def build_sign(params: dict, app_secret: str) -> str:
"""
Tracksolid signing algorithm (matches tspostman.py exactly):
1. Sort all param keys alphabetically, exclude 'sign' and empty values.
2. Concatenate key+value pairs with no separators.
3. Wrap with appSecret on both sides.
4. MD5 -> UPPERCASE 32-char string.
All values must already be strings before calling this.
"""
sorted_keys = sorted(
k for k in params
if k != "sign" and params[k] is not None and str(params[k]).strip() != ""
)
param_string = "".join(f"{k}{params[k]}" for k in sorted_keys)
raw_string = f"{app_secret}{param_string}{app_secret}"
return hashlib.md5(raw_string.encode("utf-8")).hexdigest().upper()
# ──────────────────────────────────────────────────────────────────────────────
# TRACKSOLID CLIENT
# ──────────────────────────────────────────────────────────────────────────────
class TracksolidClient:
def __init__(self, cfg: dict):
self.cfg = cfg
self._token: str | None = None
self._token_expires_at: float = 0.0
self.session = requests.Session()
# No Content-Type set here — requests sets it automatically to
# application/x-www-form-urlencoded when data= is used (matching tspostman.py)
def _post(self, params: dict) -> dict:
"""
Sign and POST params using x-www-form-urlencoded encoding.
Confirmed working approach from tspostman.py:
- Cast all values to strings
- Use data= (form-encoded), NOT json=
"""
str_params = {
k: str(v)
for k, v in params.items()
if v is not None and str(v).strip() != ""
}
str_params["sign"] = build_sign(str_params, self.cfg["app_secret"])
log.debug("POST %s params=%s", self.cfg["api_url"], str_params)
resp = self.session.post(
self.cfg["api_url"],
data=str_params, # form-encoded, NOT json=
timeout=30,
)
resp.raise_for_status()
data = resp.json()
log.debug("Response: %s", json.dumps(data))
return data
def _common_params(self, method: str) -> dict:
return {
"method": method,
"timestamp": utc_timestamp(),
"app_key": self.cfg["app_key"],
"sign_method": "md5",
"v": "1.0",
"format": "json",
}
def get_token(self) -> str:
"""Return a valid access token, fetching a new one only when needed."""
if self._token and time.time() < self._token_expires_at - 60:
log.debug("Reusing cached token.")
return self._token
log.info("Obtaining new access token ...")
params = self._common_params("jimi.oauth.token.get")
params.update({
"user_id": self.cfg["user_id"],
"user_pwd_md5": self.cfg["user_pwd_md5"],
"expires_in": self.cfg["expires_in"], # already a string per tspostman.py
})
data = self._post(params)
if data.get("code") != 0:
raise RuntimeError(
f"Auth failed — code={data.get('code')} message={data.get('message')}"
)
self._token = data["result"]["accessToken"]
self._token_expires_at = time.time() + int(data["result"]["expiresIn"])
log.info("Token acquired. Valid for %s seconds.", data["result"]["expiresIn"])
return self._token
def update_vehicle(self, imei: str, fields: dict, dry_run: bool = False) -> dict:
"""
Call jimi.open.device.update for one IMEI.
fields: dict using local key names (see row_to_fields below).
Returns the API response dict.
"""
if dry_run:
log.info("[DRY-RUN] IMEI %s -> %s", imei, fields)
return {"code": 0, "message": "dry-run"}
token = self.get_token()
params = self._common_params("jimi.open.device.update")
params["access_token"] = token
params["imei"] = str(imei)
# Map local field names -> Tracksolid API field names
api_field_map = {
"license_plate": "vehicleNumber",
"driver_name": "driverName",
"driver_phone": "driverPhone",
"vehicle_model": "vehicleModels",
"vin": "carFrame",
"engine_number": "engineNumber",
"device_name": "deviceName",
"fuel_per_100": "fuelPer100km",
}
for local_key, api_key in api_field_map.items():
val = fields.get(local_key)
if val:
params[api_key] = str(val)
return self._post(params)
# ──────────────────────────────────────────────────────────────────────────────
# CSV PARSING
# ──────────────────────────────────────────────────────────────────────────────
def clean(val) -> str | None:
"""Return None for NaN/empty values, else a stripped string."""
if pd.isna(val) or str(val).strip() in ("", "nan", "NaN"):
return None
return str(val).strip()
def row_to_fields(row: pd.Series) -> dict:
"""Map one CSV row to local field names used by update_vehicle()."""
return {
"license_plate": clean(row.get("License Plate No.")),
"driver_name": clean(row.get("Driver Name")),
"driver_phone": clean(row.get("Telephone")),
"vehicle_model": clean(row.get("Vehicle Model")),
"vin": clean(row.get("VIN")),
"engine_number": clean(row.get("Engine Number")),
"device_name": clean(row.get("Device Name")),
"fuel_per_100": clean(row.get("Fuel/100km")),
}
# ──────────────────────────────────────────────────────────────────────────────
# MAIN
# ──────────────────────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser(
description="Bulk-update Tracksolid vehicle info from CSV."
)
parser.add_argument(
"--dry-run", action="store_true",
help="Show what would be sent without making update API calls."
)
parser.add_argument(
"--csv", default=CSV_PATH,
help=f"Path to the logistics CSV (default: {CSV_PATH})"
)
parser.add_argument(
"--limit", type=int, default=None,
help="Only process the first N rows (useful for testing)."
)
args = parser.parse_args()
# ── Load CSV ───────────────────────────────────────────────────────────────
csv_file = Path(args.csv)
if not csv_file.exists():
log.error("CSV file not found: %s", csv_file)
sys.exit(1)
df = pd.read_csv(csv_file, dtype={"IMEI": str})
log.info("Loaded %d rows from %s", len(df), csv_file)
if args.limit:
df = df.head(args.limit)
log.info("Limiting to first %d rows.", args.limit)
df = df[df["IMEI"].notna() & (df["IMEI"].str.strip() != "")]
log.info("%d rows have a valid IMEI.", len(df))
if df.empty:
log.warning("No rows to process. Exiting.")
sys.exit(0)
# ── Initialise client & verify auth ───────────────────────────────────────
client = TracksolidClient(CONFIG)
if not args.dry_run:
try:
client.get_token()
except Exception as exc:
log.error("Authentication failed: %s", exc)
log.error("Check TS_USER_ID, TS_USER_PWD_MD5, TS_APP_KEY, TS_APP_SECRET.")
sys.exit(1)
# ── Process rows ───────────────────────────────────────────────────────────
results = []
success = 0
failed = 0
skipped = 0
for idx, row in df.iterrows():
imei = str(row["IMEI"]).strip()
fields = row_to_fields(row)
# Skip rows where every updatable field is empty
if not any(fields.values()):
log.warning("Row %d (IMEI %s): no updatable fields, skipping.", idx + 1, imei)
skipped += 1
continue
log.info(
"Row %d/%d — IMEI: %s | Plate: %s | Driver: %s",
idx + 1, len(df), imei,
fields.get("license_plate") or "",
fields.get("driver_name") or "",
)
try:
resp = client.update_vehicle(imei, fields, dry_run=args.dry_run)
if resp.get("code") == 0:
log.info(" OK")
success += 1
else:
log.warning(
" API error — code=%s message=%s",
resp.get("code"), resp.get("message")
)
failed += 1
results.append({
"imei": imei,
**fields,
"api_code": resp.get("code"),
"api_message": resp.get("message"),
})
except Exception as exc:
log.error(" Exception for IMEI %s: %s", imei, exc)
failed += 1
results.append({
"imei": imei,
**fields,
"api_code": "EXCEPTION",
"api_message": str(exc),
})
if not args.dry_run:
time.sleep(CONFIG["request_delay"])
# ── Summary & audit CSV ───────────────────────────────────────────────────
log.info("-" * 60)
log.info(
"Done. OK: %d Failed: %d Skipped: %d | Total: %d",
success, failed, skipped, success + failed + skipped
)
out_path = "tracksolid_update_results.csv"
pd.DataFrame(results).to_csv(out_path, index=False)
log.info("Audit results written to %s", out_path)
if __name__ == "__main__":
main()

View file

@ -1,121 +0,0 @@
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-- Migration 08 — Analytics Configuration Tables
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-- Adds reference data driving the three-stakeholder analytics redesign
-- (Phase 0.3 of the plan). These tables let downstream views monetise idle
-- and fuel costs, and apply traffic-light targets to KPIs without hard-coding
-- thresholds in SQL.
--
-- • ops.cost_rates — fuel price per litre by city, labour rate by role.
-- • ops.kpi_targets — green / amber / red thresholds per KPI per scope.
--
-- Run after migration 07. Safe to re-run (CREATE TABLE IF NOT EXISTS,
-- INSERT ... ON CONFLICT DO NOTHING).
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEGIN;
-- ── 1. ops.cost_rates ───────────────────────────────────────────────────────
-- Reference rates that power monetisation in analytics views. Lookup pattern
-- in views: WHERE scope_type = 'city' AND scope_value = <city> AND metric = ...
-- ORDER BY effective_from DESC LIMIT 1.
CREATE TABLE IF NOT EXISTS ops.cost_rates (
rate_key TEXT PRIMARY KEY,
scope_type TEXT NOT NULL, -- 'city' | 'role' | 'global'
scope_value TEXT, -- 'nairobi' | 'driver' | NULL for global
metric TEXT NOT NULL, -- 'fuel_per_litre' | 'labour_per_hour'
amount NUMERIC(12,2) NOT NULL,
currency TEXT NOT NULL, -- 'KES' | 'UGX'
effective_from DATE NOT NULL DEFAULT CURRENT_DATE,
notes TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_cost_rates_lookup
ON ops.cost_rates (scope_type, scope_value, metric, effective_from DESC);
COMMENT ON TABLE ops.cost_rates
IS 'Reference rates for analytics monetisation: fuel price per litre by city, '
'labour cost per hour by role. Resolution order in views: scope_type=city '
'> scope_type=role > scope_type=global.';
COMMENT ON COLUMN ops.cost_rates.metric
IS 'fuel_per_litre | labour_per_hour';
COMMENT ON COLUMN ops.cost_rates.scope_type
IS 'city | role | global';
-- ── 2. ops.kpi_targets ──────────────────────────────────────────────────────
-- Traffic-light thresholds per KPI. Same KPI can have global + per-CC + per-city
-- rows; views use a CASE / COALESCE chain to pick the most specific match.
CREATE TABLE IF NOT EXISTS ops.kpi_targets (
target_id BIGSERIAL PRIMARY KEY,
kpi_key TEXT NOT NULL, -- e.g. 'utilisation_pct'
scope_type TEXT NOT NULL, -- 'global' | 'city' | 'cost_centre' | 'vehicle_category'
scope_value TEXT, -- NULL for global
target_value NUMERIC(12,2) NOT NULL,
amber_threshold NUMERIC(12,2), -- between target and red
red_threshold NUMERIC(12,2), -- worse than amber
direction TEXT NOT NULL DEFAULT 'higher_is_better',
-- 'higher_is_better' | 'lower_is_better'
effective_from DATE NOT NULL DEFAULT CURRENT_DATE,
notes TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (kpi_key, scope_type, scope_value, effective_from)
);
CREATE INDEX IF NOT EXISTS idx_kpi_targets_lookup
ON ops.kpi_targets (kpi_key, scope_type, scope_value, effective_from DESC);
COMMENT ON TABLE ops.kpi_targets
IS 'Traffic-light targets per KPI per scope. Resolution order in views: '
'cost_centre > vehicle_category > city > global.';
COMMENT ON COLUMN ops.kpi_targets.direction
IS 'higher_is_better -> green when value >= target. '
'lower_is_better -> green when value <= target.';
-- ── 3. Seed cost rates ──────────────────────────────────────────────────────
-- Placeholder values — confirm with Finance and update via a follow-up insert
-- with a later effective_from date (do NOT mutate historical rows).
INSERT INTO ops.cost_rates
(rate_key, scope_type, scope_value, metric, amount, currency, notes)
VALUES
('fuel.nairobi', 'city', 'nairobi', 'fuel_per_litre', 195.00, 'KES',
'Placeholder pump price — confirm with Finance.'),
('fuel.mombasa', 'city', 'mombasa', 'fuel_per_litre', 195.00, 'KES',
'Placeholder pump price — confirm with Finance.'),
('fuel.kampala', 'city', 'kampala', 'fuel_per_litre', 5200.00, 'UGX',
'Placeholder pump price — confirm with Finance.')
ON CONFLICT (rate_key) DO NOTHING;
-- ── 4. Seed KPI targets ─────────────────────────────────────────────────────
-- Initial Exco-relevant targets. Calibrate after one month of clean data.
INSERT INTO ops.kpi_targets
(kpi_key, scope_type, scope_value, target_value, amber_threshold,
red_threshold, direction, notes)
VALUES
('utilisation_pct', 'global', NULL, 70, 60, 50, 'higher_is_better',
'Fleet utilisation: drive_hours / engine_on_hours.'),
('idle_pct', 'global', NULL, 15, 20, 25, 'lower_is_better',
'Idle as % of engine-on time.'),
('idle_pct', 'cost_centre', 'osp patrol', 15, 20, 25, 'lower_is_better',
'OSP patrol idle target — same as global until calibrated.'),
('fuel_kes_per_100km', 'global', NULL, 12, 14, 16, 'lower_is_better',
'Fuel litres per 100km equivalent — uses fuel_100km on devices.'),
('mttr_hours', 'global', NULL, 4, 6, 8, 'lower_is_better',
'Mean Time To Resolve, field-service ticket.'),
('alarms_per_100km', 'global', NULL, 2, 3, 5, 'lower_is_better',
'Safety event density.')
ON CONFLICT (kpi_key, scope_type, scope_value, effective_from) DO NOTHING;
-- ── 5. Read access for Grafana ──────────────────────────────────────────────
GRANT USAGE ON SCHEMA ops TO grafana_ro;
GRANT SELECT ON ops.cost_rates TO grafana_ro;
GRANT SELECT ON ops.kpi_targets TO grafana_ro;
COMMIT;

View file

@ -1,82 +0,0 @@
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-- Migration 09 — tracksolid.trips Enrichment
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-- The polling endpoint jimi.device.track.mileage does not return start/end
-- coordinates, fuel, idle, or trip sequence. This migration adds the columns
-- needed to enrich every poll-ingested trip from data we already have:
-- • start/end coordinates and full route polyline reconstructed from
-- position_history at insert time (see ingest_movement_rev.py::poll_trips)
-- • reverse-geocoded human-readable addresses (Nominatim)
-- • denormalised vehicle_plate so trip displays don't need a join
-- • waypoint count for audit / data-quality checks
--
-- Adds a v_trips_enriched view exposing daily_seq (Nth trip for IMEI on this
-- Africa/Nairobi date) — replaces reliance on the device-supplied trip_seq
-- which is only populated when the rarely-firing /pushtripreport webhook
-- delivers a payload.
--
-- Run after migration 08. Safe to re-run (ADD COLUMN IF NOT EXISTS,
-- CREATE INDEX IF NOT EXISTS, CREATE OR REPLACE VIEW).
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEGIN;
-- ── 1. New columns on tracksolid.trips ──────────────────────────────────────
ALTER TABLE tracksolid.trips
ADD COLUMN IF NOT EXISTS route_geom geometry(LineString, 4326),
ADD COLUMN IF NOT EXISTS start_address TEXT,
ADD COLUMN IF NOT EXISTS end_address TEXT,
ADD COLUMN IF NOT EXISTS vehicle_plate TEXT,
ADD COLUMN IF NOT EXISTS waypoints_count INTEGER;
COMMENT ON COLUMN tracksolid.trips.route_geom IS
'Full GPS route polyline built at ingest from position_history points '
'where gps_time BETWEEN start_time AND end_time. NULL when fewer than '
'2 fixes are available for the trip window.';
COMMENT ON COLUMN tracksolid.trips.start_address IS
'Reverse-geocoded human-readable address near start_geom (Nominatim). '
'NULL on lookup failure; address is best-effort, not authoritative.';
COMMENT ON COLUMN tracksolid.trips.end_address IS
'Reverse-geocoded human-readable address near end_geom (Nominatim). '
'NULL on lookup failure; address is best-effort, not authoritative.';
COMMENT ON COLUMN tracksolid.trips.vehicle_plate IS
'Denormalised tracksolid.devices.vehicle_number cached at trip-insert '
'time. Avoids a join for trip displays; refreshed only on next ingest.';
COMMENT ON COLUMN tracksolid.trips.waypoints_count IS
'Number of position_history fixes that contributed to route_geom. '
'Audit aid: 0 or 1 means route_geom is NULL or degenerate.';
-- ── 2. Spatial indexes for replay / map queries ─────────────────────────────
CREATE INDEX IF NOT EXISTS idx_trips_route_geom
ON tracksolid.trips USING GIST (route_geom);
CREATE INDEX IF NOT EXISTS idx_trips_start_geom
ON tracksolid.trips USING GIST (start_geom);
CREATE INDEX IF NOT EXISTS idx_trips_end_geom
ON tracksolid.trips USING GIST (end_geom);
-- ── 3. v_trips_enriched view ────────────────────────────────────────────────
-- Adds trip_date_eat (Africa/Nairobi local date) and daily_seq (Nth trip on
-- that date for the IMEI) without depending on the device-supplied trip_seq.
CREATE OR REPLACE VIEW tracksolid.v_trips_enriched AS
SELECT
t.*,
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS trip_date_eat,
ROW_NUMBER() OVER (
PARTITION BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date
ORDER BY t.start_time
) AS daily_seq
FROM tracksolid.trips t;
COMMENT ON VIEW tracksolid.v_trips_enriched IS
'tracksolid.trips with computed daily_seq (Nth trip per IMEI per local '
'Africa/Nairobi day) and trip_date_eat. Replaces reliance on the '
'device-supplied trip_seq column, which is NULL for poll-ingested trips.';
-- ── 4. Read access for grafana_ro ───────────────────────────────────────────
GRANT SELECT ON tracksolid.v_trips_enriched TO grafana_ro;
COMMIT;

View file

@ -1,111 +0,0 @@
-- 10_driver_clock_views.sql
-- Driver clock-in / clock-out views for n8n tardiness + working-hours monitoring.
--
-- Two views, both keyed by IMEI per local Africa/Nairobi date:
-- • v_driver_clock_daily — historical, one row per IMEI per day with activity
-- • v_driver_clock_today — thin pass-through filtered to today (EAT)
--
-- The view exposes raw times, locations, and addresses; n8n owns tardiness
-- thresholds and cost-centre filtering. Closing time is the latest end_time
-- of any trip whose start_time falls on the local Nairobi date — kept lossless
-- so n8n can detect midnight crossings via reporting_ts/closing_ts.
--
-- Reuses:
-- • tracksolid.trips.distance_km (renamed in migration 04)
-- • tracksolid.trips.driving_time_s (referenced in migration 05)
-- • tracksolid.trips.start_geom/end_geom (migration 02 §3.06)
-- • tracksolid.trips.start_address/end_address (migration 09 — Nominatim)
--
-- Pattern follows 07_analytics_views.sql: regular views (not materialised),
-- COMMENT ON VIEW with provenance, GRANT SELECT TO grafana_ro.
BEGIN;
-- ─────────────────────────────────────────────────────────────────────────────
-- v_driver_clock_daily
-- One row per IMEI per local Africa/Nairobi date with at least one trip.
-- ─────────────────────────────────────────────────────────────────────────────
CREATE OR REPLACE VIEW tracksolid.v_driver_clock_daily AS
WITH daily_agg AS (
SELECT
t.imei,
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
MIN(t.start_time) AS reporting_ts,
MAX(t.end_time) AS closing_ts,
COUNT(*) AS trips_count,
SUM(t.distance_km) AS total_km,
SUM(t.driving_time_s)::numeric / 3600 AS drive_hours
FROM tracksolid.trips t
GROUP BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date
),
start_row AS (
SELECT DISTINCT ON (t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date)
t.imei,
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
ST_Y(t.start_geom::geometry) AS start_lat,
ST_X(t.start_geom::geometry) AS start_lng,
t.start_address AS start_address
FROM tracksolid.trips t
ORDER BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date, t.start_time ASC
),
end_row AS (
SELECT DISTINCT ON (t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date)
t.imei,
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
ST_Y(t.end_geom::geometry) AS end_lat,
ST_X(t.end_geom::geometry) AS end_lng,
t.end_address AS end_address
FROM tracksolid.trips t
ORDER BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date, t.end_time DESC NULLS LAST
)
SELECT
a.imei,
d.driver_name,
d.vehicle_number,
d.cost_centre,
COALESCE(d.assigned_city, d.city, 'unassigned') AS assigned_city,
a.report_date,
(a.reporting_ts AT TIME ZONE 'Africa/Nairobi')::time AS reporting_time,
(a.closing_ts AT TIME ZONE 'Africa/Nairobi')::time AS closing_time,
a.reporting_ts,
a.closing_ts,
s.start_lat,
s.start_lng,
s.start_address,
e.end_lat,
e.end_lng,
e.end_address,
a.trips_count,
a.total_km,
a.drive_hours
FROM daily_agg a
LEFT JOIN start_row s ON s.imei = a.imei AND s.report_date = a.report_date
LEFT JOIN end_row e ON e.imei = a.imei AND e.report_date = a.report_date
LEFT JOIN tracksolid.devices d ON d.imei = a.imei;
COMMENT ON VIEW tracksolid.v_driver_clock_daily IS
'Driver clock-in / clock-out daily series. One row per IMEI per Africa/Nairobi '
'date with at least one trip. Reporting/closing times are derived from trip '
'start_time/end_time bounded by local-date start; closing_ts may cross '
'midnight UTC. No policy embedded — n8n applies tardiness rules and cost-centre '
'filtering. See plan i-would-like-to-wobbly-volcano (2026-05-04).';
GRANT SELECT ON tracksolid.v_driver_clock_daily TO grafana_ro;
-- ─────────────────────────────────────────────────────────────────────────────
-- v_driver_clock_today
-- Pass-through filter: today's row from v_driver_clock_daily.
-- ─────────────────────────────────────────────────────────────────────────────
CREATE OR REPLACE VIEW tracksolid.v_driver_clock_today AS
SELECT *
FROM tracksolid.v_driver_clock_daily
WHERE report_date = (NOW() AT TIME ZONE 'Africa/Nairobi')::date;
COMMENT ON VIEW tracksolid.v_driver_clock_today IS
'Today snapshot of v_driver_clock_daily, filtered to (NOW() AT TIME ZONE '
'''Africa/Nairobi'')::date. Refreshes as trips land throughout the day.';
GRANT SELECT ON tracksolid.v_driver_clock_today TO grafana_ro;
COMMIT;

View file

@ -1,32 +0,0 @@
-- 10_pgbouncer_auth.sql
-- pgbouncer SCRAM passthrough auth: dedicated role + user_lookup() function.
-- Runbook: 260507_pgbouncer_deployment.md
--
-- Idempotent. Re-applying is a no-op:
-- * Role created only when missing (placeholder password, replaced on every
-- container startup by run_migrations.py:sync_role_passwords from
-- PGBOUNCER_AUTH_PASSWORD).
-- * Function uses CREATE OR REPLACE.
-- * GRANT/REVOKE are safe to re-run.
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'pgbouncer') THEN
CREATE ROLE pgbouncer LOGIN PASSWORD 'SET_PASSWORD_IN_ENV';
END IF;
END
$$;
CREATE OR REPLACE FUNCTION public.user_lookup(in_user text,
OUT uname text, OUT phash text) RETURNS record AS $$
BEGIN
SELECT usename, passwd
FROM pg_catalog.pg_shadow
WHERE usename = in_user
INTO uname, phash;
RETURN;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
REVOKE ALL ON FUNCTION public.user_lookup(text) FROM public;
GRANT EXECUTE ON FUNCTION public.user_lookup(text) TO pgbouncer;

View file

@ -1,554 +0,0 @@
-- 11_reporting_schema.sql
-- Map-dashboard read layer consumed by dashboard_api_rev.py:
-- reporting.fn_live_positions / fn_vehicle_track / fn_trips_for_map
-- + the v_trips materialized view, filter/summary views, and refresh_log.
-- Captured from prod 2026-06-05 to close the reproducibility gap (these objects
-- lived only on the live DB, in no migration). Every object uses IF NOT EXISTS /
-- CREATE OR REPLACE so the file is safe to re-apply.
--
-- NOTE: the v_trips materialized view is created WITH DATA (populated once). On
-- prod it is owned by role `reporting_refresher` and kept current by an external
-- REFRESH job; that role + refresh schedule are infrastructure, NOT created here.
-- On a fresh rebuild v_trips is populated at creation but will go stale until a
-- refresh job is wired (see docs). The dashboard map functions still work, just
-- against the snapshot until then.
CREATE SCHEMA IF NOT EXISTS reporting;
-- Bodies reference base tables unqualified (devices, trips, …) + PostGIS;
-- resolve via search_path so this applies cleanly on a fresh DB.
SET search_path = tracksolid, reporting, public;
-- ── helper ───────────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION reporting.normalize_plate(p text)
RETURNS text
LANGUAGE sql
IMMUTABLE PARALLEL SAFE
AS $function$
SELECT regexp_replace(
regexp_replace(trim(p), '\s+', ' ', 'g'),
'(\d) ([A-Z])$', '\1\2'
)
$function$;
-- ── refresh audit table ──────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS reporting.refresh_log (
refreshed_at timestamptz DEFAULT now() NOT NULL,
source text DEFAULT 'n8n'::text NOT NULL,
duration_ms integer,
row_count integer,
notes text
);
-- ── v_trips materialized view (+ indexes) ────────────────────────────────────
CREATE MATERIALIZED VIEW IF NOT EXISTS reporting.v_trips AS
WITH device_trip_counts AS (
SELECT trips.imei,
count(*) AS trip_count
FROM trips
GROUP BY trips.imei
), primary_device AS (
SELECT DISTINCT ON ((reporting.normalize_plate(d_1.vehicle_number))) reporting.normalize_plate(d_1.vehicle_number) AS vehicle_number_norm,
d_1.imei AS primary_imei
FROM devices d_1
LEFT JOIN device_trip_counts c USING (imei)
WHERE d_1.vehicle_number IS NOT NULL AND d_1.enabled_flag = 1
ORDER BY (reporting.normalize_plate(d_1.vehicle_number)), (COALESCE(c.trip_count, 0::bigint)) DESC, d_1.activation_time, d_1.imei
)
SELECT t.id AS trip_id,
t.imei,
d.device_name,
reporting.normalize_plate(d.vehicle_number) AS vehicle_number,
d.vehicle_models,
d.vehicle_category,
d.cost_centre,
d.assigned_city,
d.driver_name AS assigned_driver,
(t.start_time AT TIME ZONE 'Africa/Nairobi'::text) AS start_time,
(t.end_time AT TIME ZONE 'Africa/Nairobi'::text) AS end_time,
(t.start_time AT TIME ZONE 'Africa/Nairobi'::text)::date AS trip_date,
EXTRACT(hour FROM (t.start_time AT TIME ZONE 'Africa/Nairobi'::text))::integer AS start_hour,
EXTRACT(dow FROM (t.start_time AT TIME ZONE 'Africa/Nairobi'::text))::integer AS start_dow,
row_number() OVER (PARTITION BY t.imei, ((t.start_time AT TIME ZONE 'Africa/Nairobi'::text)::date) ORDER BY t.start_time) AS daily_seq,
t.distance_km,
t.avg_speed_kmh,
t.max_speed_kmh,
t.idle_time_s,
t.driving_time_s,
t.fuel_consumed_l,
t.waypoints_count,
t.start_address,
t.end_address,
t.start_geom,
t.end_geom,
t.route_geom,
st_asgeojson(st_simplifypreservetopology(t.route_geom, 0.00005::double precision))::json AS route_geojson,
st_numpoints(t.route_geom) >= 2 AND st_length(t.route_geom::geography) > 50::double precision AS is_meaningful_route,
(t.updated_at AT TIME ZONE 'Africa/Nairobi'::text) AS updated_at
FROM trips t
LEFT JOIN devices d USING (imei)
LEFT JOIN primary_device pd ON pd.vehicle_number_norm = reporting.normalize_plate(d.vehicle_number)
WHERE d.vehicle_number IS NULL OR pd.primary_imei IS NULL OR t.imei = pd.primary_imei
WITH DATA;
CREATE INDEX IF NOT EXISTS ix_v_trips_city_trip_date ON reporting.v_trips USING btree (assigned_city, trip_date);
CREATE INDEX IF NOT EXISTS ix_v_trips_cost_centre_trip_date ON reporting.v_trips USING btree (cost_centre, trip_date);
CREATE INDEX IF NOT EXISTS ix_v_trips_driver_trip_date ON reporting.v_trips USING btree (assigned_driver, trip_date);
CREATE INDEX IF NOT EXISTS ix_v_trips_imei_trip_date ON reporting.v_trips USING btree (imei, trip_date);
CREATE INDEX IF NOT EXISTS ix_v_trips_meaningful_date ON reporting.v_trips USING btree (trip_date) WHERE is_meaningful_route;
CREATE INDEX IF NOT EXISTS ix_v_trips_trip_date ON reporting.v_trips USING btree (trip_date);
CREATE UNIQUE INDEX IF NOT EXISTS ix_v_trips_trip_id ON reporting.v_trips USING btree (trip_id);
-- ── views (dependency-ordered) ───────────────────────────────────────────────
CREATE OR REPLACE VIEW reporting.v_live_positions AS
WITH primary_device AS (
SELECT DISTINCT ON ((reporting.normalize_plate(d_1.vehicle_number))) reporting.normalize_plate(d_1.vehicle_number) AS vehicle_number,
d_1.imei AS primary_imei
FROM devices d_1
LEFT JOIN live_positions lp_1 ON lp_1.imei = d_1.imei
WHERE d_1.vehicle_number IS NOT NULL AND d_1.enabled_flag = 1
ORDER BY (reporting.normalize_plate(d_1.vehicle_number)), (
CASE
WHEN (d_1.mc_type = ANY (ARRAY['GT06E'::text, 'X3'::text, 'AT4'::text])) AND lp_1.gps_time >= (now() - '24:00:00'::interval) THEN 0
ELSE 1
END), lp_1.gps_time DESC NULLS LAST, (
CASE d_1.mc_type
WHEN 'GT06E'::text THEN 1
WHEN 'X3'::text THEN 2
WHEN 'AT4'::text THEN 3
WHEN 'JC400P'::text THEN 4
ELSE 5
END), d_1.activation_time, d_1.imei
)
SELECT lp.imei,
pd.vehicle_number,
d.driver_name AS assigned_driver,
d.cost_centre,
d.assigned_city,
d.vehicle_category,
d.vehicle_models,
d.mc_type,
CASE d.mc_type
WHEN 'GT06E'::text THEN 'tracker'::text
WHEN 'X3'::text THEN 'tracker'::text
WHEN 'AT4'::text THEN 'tracker'::text
WHEN 'JC400P'::text THEN 'camera'::text
ELSE 'other'::text
END AS device_kind,
lp.lat,
lp.lng,
lp.speed,
lp.direction,
lp.acc_status,
lp.device_status,
lp.gps_signal,
lp.gps_num,
lp.current_mileage,
lp.loc_desc,
lp.gps_time,
lp.updated_at,
(lp.gps_time AT TIME ZONE 'Africa/Nairobi'::text) AS gps_time_eat,
(lp.updated_at AT TIME ZONE 'Africa/Nairobi'::text) AS updated_at_eat,
round(EXTRACT(epoch FROM now() - lp.gps_time) / 3600::numeric, 2) AS source_age_hours
FROM live_positions lp
JOIN primary_device pd ON pd.primary_imei = lp.imei
JOIN devices d ON d.imei = lp.imei;
CREATE OR REPLACE VIEW reporting.v_trips_today AS
SELECT trip_id,
imei,
device_name,
vehicle_number,
vehicle_models,
vehicle_category,
cost_centre,
assigned_city,
assigned_driver,
start_time,
end_time,
trip_date,
start_hour,
start_dow,
daily_seq,
distance_km,
avg_speed_kmh,
max_speed_kmh,
idle_time_s,
driving_time_s,
fuel_consumed_l,
waypoints_count,
start_address,
end_address,
start_geom,
end_geom,
route_geom,
route_geojson,
is_meaningful_route,
updated_at
FROM reporting.v_trips
WHERE trip_date = (now() AT TIME ZONE 'Africa/Nairobi'::text)::date;
CREATE OR REPLACE VIEW reporting.v_filter_drivers AS
SELECT DISTINCT assigned_driver AS driver
FROM reporting.v_trips
WHERE assigned_driver IS NOT NULL
ORDER BY assigned_driver;
CREATE OR REPLACE VIEW reporting.v_filter_cost_centres AS
SELECT DISTINCT cost_centre
FROM reporting.v_trips
WHERE cost_centre IS NOT NULL
ORDER BY cost_centre;
CREATE OR REPLACE VIEW reporting.v_filter_vehicles AS
SELECT vehicle_number,
string_agg(DISTINCT assigned_driver, ', '::text ORDER BY assigned_driver) AS drivers,
(array_agg(cost_centre ORDER BY start_time DESC NULLS LAST))[1] AS cost_centre,
(array_agg(assigned_city ORDER BY start_time DESC NULLS LAST))[1] AS assigned_city
FROM reporting.v_trips
WHERE vehicle_number IS NOT NULL
GROUP BY vehicle_number
ORDER BY vehicle_number;
CREATE OR REPLACE VIEW reporting.v_filter_cities AS
SELECT DISTINCT assigned_city
FROM reporting.v_trips
WHERE assigned_city IS NOT NULL
ORDER BY assigned_city;
CREATE OR REPLACE VIEW reporting.v_daily_summary AS
SELECT trip_date,
cost_centre,
assigned_city,
vehicle_number,
assigned_driver,
count(*) AS trip_count,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
round(100.0 * sum(idle_time_s)::numeric / NULLIF(sum(idle_time_s + driving_time_s), 0)::numeric, 1) AS idle_pct,
min(start_time) AS first_trip_start,
max(end_time) AS last_trip_end,
avg(avg_speed_kmh) AS avg_speed_kmh,
max(max_speed_kmh) AS max_speed_kmh,
st_asgeojson(st_simplifypreservetopology(st_collect(route_geom), 0.00005::double precision))::json AS day_routes_geojson
FROM reporting.v_trips
WHERE is_meaningful_route
GROUP BY trip_date, cost_centre, assigned_city, vehicle_number, assigned_driver;
CREATE OR REPLACE VIEW reporting.v_weekly_summary AS
SELECT date_trunc('week'::text, trip_date::timestamp with time zone)::date AS week_start,
cost_centre,
assigned_city,
vehicle_number,
assigned_driver,
count(*) AS trip_count,
count(DISTINCT trip_date) AS active_days,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
avg(distance_km) AS avg_trip_km
FROM reporting.v_trips
WHERE is_meaningful_route
GROUP BY (date_trunc('week'::text, trip_date::timestamp with time zone)::date), cost_centre, assigned_city, vehicle_number, assigned_driver;
CREATE OR REPLACE VIEW reporting.v_monthly_summary AS
SELECT date_trunc('month'::text, trip_date::timestamp with time zone)::date AS month_start,
to_char(trip_date::timestamp with time zone, 'YYYY-MM'::text) AS month_label,
cost_centre,
assigned_city,
vehicle_category,
vehicle_number,
assigned_driver,
count(*) AS trip_count,
count(DISTINCT trip_date) AS active_days,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
round(100.0 * sum(idle_time_s)::numeric / NULLIF(sum(idle_time_s + driving_time_s), 0)::numeric, 1) AS idle_pct,
round(sum(distance_km) / NULLIF(count(DISTINCT trip_date), 0)::numeric, 1) AS km_per_active_day,
round(sum(distance_km) / NULLIF(count(*), 0)::numeric, 1) AS km_per_trip,
avg(avg_speed_kmh) AS avg_speed_kmh,
max(max_speed_kmh) AS peak_speed_kmh
FROM reporting.v_trips
WHERE is_meaningful_route
GROUP BY (date_trunc('month'::text, trip_date::timestamp with time zone)::date), (to_char(trip_date::timestamp with time zone, 'YYYY-MM'::text)), cost_centre, assigned_city, vehicle_category, vehicle_number, assigned_driver;
CREATE OR REPLACE VIEW reporting.v_daily_cost_centre AS
SELECT trip_date,
cost_centre,
count(DISTINCT imei) AS active_vehicles,
count(DISTINCT assigned_driver) AS active_drivers,
count(*) AS trip_count,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
round(100.0 * sum(idle_time_s)::numeric / NULLIF(sum(idle_time_s + driving_time_s), 0)::numeric, 1) AS idle_pct,
round(sum(distance_km) / NULLIF(count(DISTINCT imei), 0)::numeric, 1) AS km_per_vehicle
FROM reporting.v_trips
WHERE is_meaningful_route AND cost_centre IS NOT NULL
GROUP BY trip_date, cost_centre;
CREATE OR REPLACE VIEW reporting.v_weekly_cost_centre AS
SELECT date_trunc('week'::text, trip_date::timestamp with time zone)::date AS week_start,
cost_centre,
count(DISTINCT imei) AS active_vehicles,
count(DISTINCT assigned_driver) AS active_drivers,
count(DISTINCT trip_date) AS active_days,
count(*) AS trip_count,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
round(100.0 * sum(idle_time_s)::numeric / NULLIF(sum(idle_time_s + driving_time_s), 0)::numeric, 1) AS idle_pct,
round(sum(distance_km) / NULLIF(count(DISTINCT imei), 0)::numeric, 1) AS km_per_vehicle
FROM reporting.v_trips
WHERE is_meaningful_route AND cost_centre IS NOT NULL
GROUP BY (date_trunc('week'::text, trip_date::timestamp with time zone)::date), cost_centre;
CREATE OR REPLACE VIEW reporting.v_monthly_cost_centre AS
SELECT date_trunc('month'::text, trip_date::timestamp with time zone)::date AS month_start,
to_char(trip_date::timestamp with time zone, 'YYYY-MM'::text) AS month_label,
cost_centre,
count(DISTINCT imei) AS active_vehicles,
count(DISTINCT assigned_driver) AS active_drivers,
count(DISTINCT trip_date) AS active_days,
count(*) AS trip_count,
sum(distance_km) AS total_km,
sum(driving_time_s)::numeric / 3600.0 AS driving_hours,
sum(idle_time_s)::numeric / 3600.0 AS idle_hours,
round(100.0 * sum(idle_time_s)::numeric / NULLIF(sum(idle_time_s + driving_time_s), 0)::numeric, 1) AS idle_pct,
round(sum(distance_km) / NULLIF(count(DISTINCT imei), 0)::numeric, 1) AS km_per_vehicle
FROM reporting.v_trips
WHERE is_meaningful_route AND cost_centre IS NOT NULL
GROUP BY (date_trunc('month'::text, trip_date::timestamp with time zone)::date), (to_char(trip_date::timestamp with time zone, 'YYYY-MM'::text)), cost_centre;
-- ── refresh_log index ────────────────────────────────────────────────────────
CREATE INDEX IF NOT EXISTS ix_refresh_log_refreshed_at ON reporting.refresh_log USING btree (refreshed_at DESC);
-- ── map functions ────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION reporting.fn_live_positions(p_cost_centre text DEFAULT NULL::text, p_acc_status text DEFAULT NULL::text)
RETURNS jsonb
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
v_result jsonb;
BEGIN
p_cost_centre := NULLIF(p_cost_centre, '');
p_acc_status := NULLIF(p_acc_status, '');
WITH filtered AS (
SELECT * FROM reporting.v_live_positions
WHERE (p_cost_centre IS NULL OR cost_centre = p_cost_centre)
AND (p_acc_status IS NULL OR acc_status = p_acc_status)
)
SELECT jsonb_build_object(
'summary', jsonb_build_object(
'vehicle_count', COUNT(*),
-- "moving" and "parked" both restrict to devices that have reported
-- within the OFFLINE_THRESHOLD (24 h) so they represent the live
-- fleet, not equipment-failure stragglers. "offline" is its own
-- counter for the > 24 h tail.
'moving', COUNT(*) FILTER (WHERE acc_status = '1'
AND source_age_hours < 24),
'parked', COUNT(*) FILTER (WHERE acc_status = '0'
AND source_age_hours < 24),
'offline', COUNT(*) FILTER (WHERE source_age_hours >= 24),
'median_speed_moving', percentile_cont(0.5) WITHIN GROUP (ORDER BY speed)
FILTER (WHERE acc_status = '1'
AND source_age_hours < 24
AND speed > 0),
'last_batch_at', to_char(MAX(updated_at) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'oldest_fix_at', to_char(MIN(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'newest_fix_at', to_char(MAX(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'last_batch_utc', MAX(updated_at),
'newest_fix_utc', MAX(gps_time)
),
'geojson', jsonb_build_object(
'type', 'FeatureCollection',
'features', COALESCE(jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'properties', jsonb_build_object(
'imei', imei,
'vehicle_number', vehicle_number,
'driver', assigned_driver,
'cost_centre', cost_centre,
'assigned_city', assigned_city,
'vehicle_category', vehicle_category,
'mc_type', mc_type,
'device_kind', device_kind,
'source_age_hours', source_age_hours,
'speed', speed,
'direction', direction,
'acc_status', acc_status,
'device_status', device_status,
'gps_signal', gps_signal,
'gps_num', gps_num,
'current_mileage', current_mileage,
'loc_desc', loc_desc,
'gps_time', to_char(gps_time AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'updated_at', to_char(updated_at AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'gps_time_utc', gps_time,
'updated_at_utc', updated_at
),
'geometry', jsonb_build_object(
'type', 'Point',
'coordinates', jsonb_build_array(lng, lat)
)
)
), '[]'::jsonb)
)
) INTO v_result FROM filtered;
RETURN v_result;
END $function$;
CREATE OR REPLACE FUNCTION reporting.fn_vehicle_track(p_vehicle_number text, p_hours integer DEFAULT 1)
RETURNS jsonb
LANGUAGE sql
STABLE
AS $function$
-- IMEI lookup reuses the already-deduped reporting.v_live_positions instead
-- of re-running the primary_device CTE against tracksolid.trips. That keeps
-- reporting_reader off tracksolid.trips entirely.
WITH pts AS (
SELECT ph.gps_time, ph.lat, ph.lng, ph.speed, ph.direction
FROM tracksolid.position_history ph
JOIN reporting.v_live_positions lv ON lv.imei = ph.imei
WHERE lv.vehicle_number = reporting.normalize_plate(p_vehicle_number)
AND ph.gps_time >= NOW() - make_interval(hours => GREATEST(p_hours, 1))
ORDER BY ph.gps_time
)
SELECT jsonb_build_object(
'type', 'Feature',
'properties', jsonb_build_object(
'vehicle_number', reporting.normalize_plate(p_vehicle_number),
'hours', p_hours,
'points', (SELECT COUNT(*) FROM pts),
'first_fix', (SELECT to_char(MIN(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS') FROM pts),
'last_fix', (SELECT to_char(MAX(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS') FROM pts)
),
'geometry', jsonb_build_object(
'type', 'LineString',
'coordinates', COALESCE(
(SELECT jsonb_agg(jsonb_build_array(lng, lat) ORDER BY gps_time) FROM pts),
'[]'::jsonb)
)
);
$function$;
CREATE OR REPLACE FUNCTION reporting.fn_trips_for_map(p_vehicle_numbers text[] DEFAULT NULL::text[], p_driver text DEFAULT NULL::text, p_cost_centre text DEFAULT NULL::text, p_assigned_city text DEFAULT NULL::text, p_start_date date DEFAULT NULL::date, p_end_date date DEFAULT NULL::date)
RETURNS jsonb
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
v_start date := COALESCE(p_start_date, (NOW() AT TIME ZONE 'Africa/Nairobi')::date);
v_end date := COALESCE(p_end_date, (NOW() AT TIME ZONE 'Africa/Nairobi')::date);
v_days int := v_end - v_start + 1;
v_result jsonb;
BEGIN
p_driver := NULLIF(p_driver, '');
p_cost_centre := NULLIF(p_cost_centre, '');
p_assigned_city := NULLIF(p_assigned_city, '');
-- 31-day guardrail: tripped only when NO filter is set AND range > 31 days.
-- Vehicle list (non-empty), driver, cost-centre, OR city each waives it.
IF (p_vehicle_numbers IS NULL OR cardinality(p_vehicle_numbers) = 0)
AND p_driver IS NULL
AND p_cost_centre IS NULL
AND p_assigned_city IS NULL
AND v_days > 31 THEN
RAISE EXCEPTION
'Range too wide for trip-grain map (% days). Pick a vehicle, driver, cost centre, or city — or narrow the period to 31 days or fewer.',
v_days
USING ERRCODE = 'check_violation';
END IF;
WITH filtered AS (
SELECT *
FROM reporting.v_trips
WHERE is_meaningful_route
AND (p_vehicle_numbers IS NULL
OR cardinality(p_vehicle_numbers) = 0
OR vehicle_number = ANY(p_vehicle_numbers))
AND (p_driver IS NULL OR assigned_driver = p_driver)
AND (p_cost_centre IS NULL OR cost_centre = p_cost_centre)
AND (p_assigned_city IS NULL OR assigned_city = p_assigned_city)
AND (p_start_date IS NULL OR trip_date >= p_start_date)
AND (p_end_date IS NULL OR trip_date <= p_end_date)
)
SELECT jsonb_build_object(
'summary', jsonb_build_object(
'trip_count', COUNT(*),
'total_km', ROUND(COALESCE(SUM(distance_km), 0)::numeric, 1),
'driving_hours', ROUND((COALESCE(SUM(driving_time_s), 0) / 3600.0)::numeric, 1),
'idle_hours', ROUND((COALESCE(SUM(idle_time_s), 0) / 3600.0)::numeric, 1),
'unique_vehicles', COUNT(DISTINCT vehicle_number),
'unique_drivers', COUNT(DISTINCT assigned_driver),
'date_min', MIN(trip_date),
'date_max', MAX(trip_date),
-- First trip's start (chronologically first) + reverse-geocoded location
'first_trip_start_time',
(array_agg(to_char(start_time, 'YYYY-MM-DD HH24:MI:SS') ORDER BY start_time))[1],
'first_trip_start_address',
(array_agg(start_address ORDER BY start_time))[1],
'first_trip_vehicle',
(array_agg(vehicle_number ORDER BY start_time))[1],
-- Last trip's end (chronologically latest) + reverse-geocoded location
'last_trip_end_time',
(array_agg(to_char(end_time, 'YYYY-MM-DD HH24:MI:SS') ORDER BY end_time DESC NULLS LAST))[1],
'last_trip_end_address',
(array_agg(end_address ORDER BY end_time DESC NULLS LAST))[1],
'last_trip_vehicle',
(array_agg(vehicle_number ORDER BY end_time DESC NULLS LAST))[1]
),
'geojson', jsonb_build_object(
'type', 'FeatureCollection',
'features', COALESCE(jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'properties', jsonb_build_object(
'trip_id', trip_id,
'vehicle_number', vehicle_number,
'driver', assigned_driver,
'cost_centre', cost_centre,
'assigned_city', assigned_city,
'trip_date', trip_date,
'daily_seq', daily_seq,
'start_time', to_char(start_time, 'YYYY-MM-DD HH24:MI:SS'),
'end_time', to_char(end_time, 'YYYY-MM-DD HH24:MI:SS'),
'distance_km', ROUND(COALESCE(distance_km, 0)::numeric, 2),
'duration_min', ROUND((COALESCE(driving_time_s, 0) / 60.0)::numeric, 0)
),
'geometry', route_geojson
)
ORDER BY vehicle_number, trip_date, daily_seq
), '[]'::jsonb)
)
)
INTO v_result
FROM filtered;
RETURN v_result;
END
$function$;
-- ── grants (guarded: roles may not exist on a fresh DB) ───────────────────────
DO $grants$
BEGIN
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname='grafana_ro') THEN
GRANT USAGE ON SCHEMA reporting TO grafana_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA reporting TO grafana_ro;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA reporting TO grafana_ro;
END IF;
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname='tracksolid_owner') THEN
GRANT USAGE ON SCHEMA reporting TO tracksolid_owner;
END IF;
END $grants$;

View file

@ -1,30 +0,0 @@
-- 12_drop_ops.sql
-- Purge the dormant `ops` schema (workshop / tickets / dispatch / SLA / odometer)
-- and the dispatch/SLA artefacts that lived in `tracksolid`. These features were
-- never implemented and may take a different direction; the schema and views were
-- empty (or seed-only) and unused by the live map/dashboard pipeline.
--
-- Created by migrations 06 (ops schema + dispatch_log), 07 (v_sla_inflight) and
-- 08 (ops.cost_rates / ops.kpi_targets seed). Per the repo rule we do NOT rewrite
-- those applied migrations — this forward migration drops the objects instead. On
-- a fresh rebuild 06/07/08 create them, then this file removes them again.
--
-- Pre-drop snapshot of the only seeded tables: docs/reports/260605_ops_purge_backup.md
-- (the seed is also reproducible from 08_analytics_config.sql).
--
-- Every statement is IF EXISTS so the file is safe to re-apply.
--
-- NOTE: dwh_gold and tracksolid.v_utilisation_daily are intentionally NOT touched
-- here — that is a separate decision.
-- View first: it reads ops.tickets + tracksolid.dispatch_log, so it must go before
-- the objects it depends on (avoids an implicit CASCADE surprise).
DROP VIEW IF EXISTS tracksolid.v_sla_inflight;
-- The whole ops schema: tickets, service_log, odometer_readings, cost_rates,
-- kpi_targets, and the view vw_service_forecast. CASCADE clears intra-schema deps.
DROP SCHEMA IF EXISTS ops CASCADE;
-- Dispatch feature table — lived in the tracksolid schema, empty, only fed
-- v_sla_inflight (now dropped).
DROP TABLE IF EXISTS tracksolid.dispatch_log;

View file

@ -1,23 +0,0 @@
-- 13_drop_dwh_gold.sql
-- Purge the dormant `dwh_gold` aggregate schema and its dependent view. The nightly
-- ETL (dwh_gold.refresh_daily_metrics) was never scheduled, both fact/dim tables were
-- empty, and nothing in the live map/dashboard pipeline reads them. These analytics
-- may take a different direction later.
--
-- Created by migrations 02 (schema), 05 (dwh_gold expansion + refresh_daily_metrics)
-- and 07 (tracksolid.v_utilisation_daily). Per the repo rule we do NOT rewrite those
-- applied migrations — this forward migration drops the objects instead. On a fresh
-- rebuild 02/05/07 create them, then this file removes them again.
--
-- Both tables were empty at drop time, so there is no data backup (cf. the ops purge,
-- which had seed rows — docs/reports/260605_ops_purge_backup.md). Companion to
-- 12_drop_ops.sql; together they retire the unused ops + dwh_gold analytics layers.
--
-- Every statement is IF EXISTS so the file is safe to re-apply.
-- View first: it reads dwh_gold.dim_vehicles + dwh_gold.fact_daily_fleet_metrics.
DROP VIEW IF EXISTS tracksolid.v_utilisation_daily;
-- The whole dwh_gold schema: dim_vehicles, fact_daily_fleet_metrics, the
-- dim_vehicles sequence/indexes, and the refresh_daily_metrics() function.
DROP SCHEMA IF EXISTS dwh_gold CASCADE;

View file

@ -1,104 +0,0 @@
-- 14_fleet_segment_and_vehicles_view.sql
-- Fleet segmentation + de-duplicated vehicle roster.
--
-- Splits the fleet into ticket-closing FIELD SERVICE vehicles vs SPECIALIST plant
-- (cranes / pick-ups / motorbikes) that do NOT close immediate customer tickets.
--
-- The segment is DERIVED, not stored: it is computed from tracksolid.devices.vehicle_models,
-- which is itself an authoritative Tracksolid API field (sync_devices() maps
-- jimi.user.device.list -> vehicleModels, refreshed daily). Keeping it derived means it
-- always tracks the API and needs no re-seeding. The manual tracksolid.vehicle_category
-- column is intentionally NOT used here.
--
-- reporting.v_vehicles collapses the GPS-tracker + dashcam device pairs into one row per
-- vehicle, reusing reporting.normalize_plate() and the same "primary device per normalized
-- plate" precedence as reporting.v_trips / reporting.v_live_positions (migration 11). This
-- auto-merges plate-spacing duplicates (e.g. 'KDS 453Y' vs 'KDS 453 Y') and resolves any
-- within-plate model disagreement by letting the primary tracker's value win.
--
-- Every object uses CREATE OR REPLACE / guarded grants so the file is safe to re-apply.
-- Provenance: docs/reports/260608_fleet_registry_data_quality.md + ~/.claude plan binary-singing-wave.
SET search_path = tracksolid, reporting, public;
-- ── classification rule (single source of truth) ─────────────────────────────
CREATE OR REPLACE FUNCTION reporting.fn_fleet_segment(model text)
RETURNS text
LANGUAGE sql
IMMUTABLE PARALLEL SAFE
AS $function$
SELECT CASE lower(coalesce(trim(model), ''))
WHEN '' THEN 'unassigned' -- no model on record -> triage
WHEN 'crane' THEN 'specialist'
WHEN 'pick-up' THEN 'specialist'
WHEN 'pickup' THEN 'specialist'
WHEN 'truck' THEN 'specialist'
WHEN 'motorbike' THEN 'specialist'
ELSE 'field_service' -- Probox, Mazda, Van, Station Wagon, Vezel + any other named model
END
$function$;
COMMENT ON FUNCTION reporting.fn_fleet_segment(text) IS
'Maps tracksolid.devices.vehicle_models -> field_service | specialist | unassigned. '
'Specialist = crane/pick-up/motorbike/truck (do not close immediate customer tickets).';
-- ── de-duplicated vehicle roster (one row per physical vehicle) ───────────────
CREATE OR REPLACE VIEW reporting.v_vehicles AS
WITH device_trip_counts AS (
SELECT trips.imei, count(*) AS trip_count
FROM trips
GROUP BY trips.imei
), primary_device AS (
SELECT DISTINCT ON ((reporting.normalize_plate(d.vehicle_number)))
reporting.normalize_plate(d.vehicle_number) AS plate,
d.imei AS primary_imei,
d.vehicle_models,
d.driver_name,
d.driver_phone,
d.account,
d.assigned_city
FROM devices d
LEFT JOIN device_trip_counts c USING (imei)
WHERE d.vehicle_number IS NOT NULL AND d.enabled_flag = 1
ORDER BY (reporting.normalize_plate(d.vehicle_number)),
(CASE WHEN d.mc_type = ANY (ARRAY['GT06E','X3','AT4']) THEN 0 ELSE 1 END),
(COALESCE(c.trip_count, 0::bigint)) DESC,
d.activation_time,
d.imei
), plate_agg AS (
SELECT reporting.normalize_plate(d.vehicle_number) AS plate,
bool_or(d.mc_type = ANY (ARRAY['GT06E','X3','AT4'])) AS has_tracker,
bool_or(d.mc_type = 'JC400P') AS has_camera,
count(*) AS device_count
FROM devices d
WHERE d.vehicle_number IS NOT NULL AND d.enabled_flag = 1
GROUP BY reporting.normalize_plate(d.vehicle_number)
)
SELECT pd.plate,
pd.vehicle_models AS vehicle_type,
reporting.fn_fleet_segment(pd.vehicle_models) AS fleet_segment,
pd.driver_name AS driver,
pd.driver_phone,
pd.account,
pd.assigned_city,
pa.has_tracker,
pa.has_camera,
pa.device_count,
pd.primary_imei
FROM primary_device pd
JOIN plate_agg pa USING (plate);
COMMENT ON VIEW reporting.v_vehicles IS
'One row per physical vehicle (tracker+dashcam pairs collapsed by normalize_plate, primary '
'device = tracker-first then trip-count). fleet_segment derived from API-authoritative '
'vehicle_models. Source: docs/reports/260608_fleet_registry_data_quality.md.';
-- ── grants (guarded: roles may not exist on a fresh DB) ───────────────────────
DO $grants$
BEGIN
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
GRANT USAGE ON SCHEMA reporting TO grafana_ro;
GRANT EXECUTE ON FUNCTION reporting.fn_fleet_segment(text) TO grafana_ro;
GRANT SELECT ON reporting.v_vehicles TO grafana_ro;
END IF;
END $grants$;

View file

@ -1,105 +0,0 @@
-- 15_map_exclude_cost_centres.sql
-- Hide non-operational vehicles from the LIVE tracking map (FleetNow + liveposition SPA).
--
-- A small, ops-editable config table lists the cost centres to exclude. reporting.v_live_positions
-- (the base view behind reporting.fn_live_positions, which dashboard_api serves) filters out any
-- plate whose device(s) carry an excluded cost centre. Editing the table changes the map on the
-- next query — no code change, no redeploy.
--
-- Scope: LIVE map only. Trip history (reporting.v_trips materialised view) is deliberately NOT
-- touched. Initial exclusions: personal + management (staff/personal cars) and mtn (the MTN
-- contract / Uganda-Kampala fleet, outside Kenyan ops).
--
-- The v_live_positions body below is reproduced verbatim from the live prod definition
-- (== migrations/11_reporting_schema.sql) with a single added filter in the primary_device CTE.
-- Safe to re-apply (CREATE TABLE IF NOT EXISTS / INSERT ON CONFLICT / CREATE OR REPLACE VIEW).
SET search_path = tracksolid, reporting, public;
-- ── exclusion config (data-driven, editable without a migration) ──────────────
CREATE TABLE IF NOT EXISTS reporting.map_excluded_cost_centres (
cost_centre text PRIMARY KEY, -- compared case-insensitively (store lowercase)
note text,
added_at timestamptz NOT NULL DEFAULT now()
);
INSERT INTO reporting.map_excluded_cost_centres (cost_centre, note) VALUES
('personal', 'staff/personal vehicles — not operational fleet'),
('management', 'management vehicles — not operational fleet'),
('mtn', 'MTN contract / Uganda (Kampala) — outside Kenyan ops')
ON CONFLICT (cost_centre) DO NOTHING;
-- ── v_live_positions: same definition + exclusion filter ──────────────────────
CREATE OR REPLACE VIEW reporting.v_live_positions AS
WITH primary_device AS (
SELECT DISTINCT ON ((reporting.normalize_plate(d_1.vehicle_number))) reporting.normalize_plate(d_1.vehicle_number) AS vehicle_number,
d_1.imei AS primary_imei
FROM devices d_1
LEFT JOIN live_positions lp_1 ON lp_1.imei = d_1.imei
WHERE d_1.vehicle_number IS NOT NULL AND d_1.enabled_flag = 1
-- exclude plates whose device(s) carry a non-operational cost centre
AND reporting.normalize_plate(d_1.vehicle_number) NOT IN (
SELECT reporting.normalize_plate(x.vehicle_number)
FROM devices x
WHERE x.vehicle_number IS NOT NULL
AND lower(trim(x.cost_centre)) IN (
SELECT cost_centre FROM reporting.map_excluded_cost_centres)
)
ORDER BY (reporting.normalize_plate(d_1.vehicle_number)), (
CASE
WHEN (d_1.mc_type = ANY (ARRAY['GT06E'::text, 'X3'::text, 'AT4'::text])) AND lp_1.gps_time >= (now() - '24:00:00'::interval) THEN 0
ELSE 1
END), lp_1.gps_time DESC NULLS LAST, (
CASE d_1.mc_type
WHEN 'GT06E'::text THEN 1
WHEN 'X3'::text THEN 2
WHEN 'AT4'::text THEN 3
WHEN 'JC400P'::text THEN 4
ELSE 5
END), d_1.activation_time, d_1.imei
)
SELECT lp.imei,
pd.vehicle_number,
d.driver_name AS assigned_driver,
d.cost_centre,
d.assigned_city,
d.vehicle_category,
d.vehicle_models,
d.mc_type,
CASE d.mc_type
WHEN 'GT06E'::text THEN 'tracker'::text
WHEN 'X3'::text THEN 'tracker'::text
WHEN 'AT4'::text THEN 'tracker'::text
WHEN 'JC400P'::text THEN 'camera'::text
ELSE 'other'::text
END AS device_kind,
lp.lat,
lp.lng,
lp.speed,
lp.direction,
lp.acc_status,
lp.device_status,
lp.gps_signal,
lp.gps_num,
lp.current_mileage,
lp.loc_desc,
lp.gps_time,
lp.updated_at,
(lp.gps_time AT TIME ZONE 'Africa/Nairobi'::text) AS gps_time_eat,
(lp.updated_at AT TIME ZONE 'Africa/Nairobi'::text) AS updated_at_eat,
round(EXTRACT(epoch FROM now() - lp.gps_time) / 3600::numeric, 2) AS source_age_hours
FROM live_positions lp
JOIN primary_device pd ON pd.primary_imei = lp.imei
JOIN devices d ON d.imei = lp.imei;
COMMENT ON TABLE reporting.map_excluded_cost_centres IS
'Cost centres hidden from the live map (reporting.v_live_positions). Edit to hide/restore; '
'effective on next query. Seeded: personal, management, mtn. See migration 15.';
-- ── grants (guarded: roles may not exist on a fresh DB) ───────────────────────
DO $grants$
BEGIN
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
GRANT SELECT ON reporting.map_excluded_cost_centres TO grafana_ro;
END IF;
END $grants$;

View file

@ -1,99 +0,0 @@
-- 16_live_feed_vehicle_type.sql
-- Expose vehicle_type + fleet_segment on the live-map GeoJSON feed so FleetNow can give the
-- specialist vehicles (Crane / Motorbike / Pick-Up) their own marker icons. All other vehicles
-- (field-service + unassigned) keep their current marker — FleetNow only overrides icons when
-- vehicle_type is one of the specialist types.
--
-- reporting.fn_live_positions is reproduced verbatim from the live prod definition
-- (== migrations/11_reporting_schema.sql, captured via pg_get_functiondef) with TWO added
-- feature properties:
-- 'vehicle_type' = devices.vehicle_models (authoritative API type, surfaced by v_live_positions)
-- 'fleet_segment' = reporting.fn_fleet_segment(vehicle_models) (field_service|specialist|unassigned)
-- No signature change, so dependents are unaffected; STABLE function, read immediately by
-- dashboard_api (no redeploy/restart). Safe to re-apply (CREATE OR REPLACE).
SET search_path = tracksolid, reporting, public;
CREATE OR REPLACE FUNCTION reporting.fn_live_positions(p_cost_centre text DEFAULT NULL::text, p_acc_status text DEFAULT NULL::text)
RETURNS jsonb
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
v_result jsonb;
BEGIN
p_cost_centre := NULLIF(p_cost_centre, '');
p_acc_status := NULLIF(p_acc_status, '');
WITH filtered AS (
SELECT * FROM reporting.v_live_positions
WHERE (p_cost_centre IS NULL OR cost_centre = p_cost_centre)
AND (p_acc_status IS NULL OR acc_status = p_acc_status)
)
SELECT jsonb_build_object(
'summary', jsonb_build_object(
'vehicle_count', COUNT(*),
-- "moving" and "parked" both restrict to devices that have reported
-- within the OFFLINE_THRESHOLD (24 h) so they represent the live
-- fleet, not equipment-failure stragglers. "offline" is its own
-- counter for the > 24 h tail.
'moving', COUNT(*) FILTER (WHERE acc_status = '1'
AND source_age_hours < 24),
'parked', COUNT(*) FILTER (WHERE acc_status = '0'
AND source_age_hours < 24),
'offline', COUNT(*) FILTER (WHERE source_age_hours >= 24),
'median_speed_moving', percentile_cont(0.5) WITHIN GROUP (ORDER BY speed)
FILTER (WHERE acc_status = '1'
AND source_age_hours < 24
AND speed > 0),
'last_batch_at', to_char(MAX(updated_at) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'oldest_fix_at', to_char(MIN(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'newest_fix_at', to_char(MAX(gps_time) AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'last_batch_utc', MAX(updated_at),
'newest_fix_utc', MAX(gps_time)
),
'geojson', jsonb_build_object(
'type', 'FeatureCollection',
'features', COALESCE(jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'properties', jsonb_build_object(
'imei', imei,
'vehicle_number', vehicle_number,
'driver', assigned_driver,
'cost_centre', cost_centre,
'assigned_city', assigned_city,
'vehicle_category', vehicle_category,
'vehicle_type', vehicle_models,
'fleet_segment', reporting.fn_fleet_segment(vehicle_models),
'mc_type', mc_type,
'device_kind', device_kind,
'source_age_hours', source_age_hours,
'speed', speed,
'direction', direction,
'acc_status', acc_status,
'device_status', device_status,
'gps_signal', gps_signal,
'gps_num', gps_num,
'current_mileage', current_mileage,
'loc_desc', loc_desc,
'gps_time', to_char(gps_time AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'updated_at', to_char(updated_at AT TIME ZONE 'Africa/Nairobi',
'YYYY-MM-DD HH24:MI:SS'),
'gps_time_utc', gps_time,
'updated_at_utc', updated_at
),
'geometry', jsonb_build_object(
'type', 'Point',
'coordinates', jsonb_build_array(lng, lat)
)
)
), '[]'::jsonb)
)
) INTO v_result FROM filtered;
RETURN v_result;
END $function$;

View file

@ -31,15 +31,6 @@ MIGRATIONS = [
"05_enhancement_migration.sql", # new tables, OBD columns, dwh_gold expansion "05_enhancement_migration.sql", # new tables, OBD columns, dwh_gold expansion
"06_business_analytics_migration.sql", # ops schema, dispatch_log, assigned_city "06_business_analytics_migration.sql", # ops schema, dispatch_log, assigned_city
"07_analytics_views.sql", # Grafana-facing views in tracksolid.* "07_analytics_views.sql", # Grafana-facing views in tracksolid.*
"08_analytics_config.sql", # ops.cost_rates, ops.kpi_targets + seed data
"09_trips_enrichment.sql", # trips.route_geom + addresses + plate + v_trips_enriched
"10_pgbouncer_auth.sql", # pgbouncer role + user_lookup() for SCRAM passthrough
"11_reporting_schema.sql", # reporting.* map-dashboard read layer (dashboard_api)
"12_drop_ops.sql", # purge dormant ops schema + dispatch_log + v_sla_inflight
"13_drop_dwh_gold.sql", # purge dormant dwh_gold schema + v_utilisation_daily
"14_fleet_segment_and_vehicles_view.sql", # reporting.fn_fleet_segment + reporting.v_vehicles roster
"15_map_exclude_cost_centres.sql", # hide personal/management/mtn vehicles from the live map
"16_live_feed_vehicle_type.sql", # add vehicle_type + fleet_segment to fn_live_positions feed
] ]
# ── Tables that must exist before the service is allowed to start ───────────── # ── Tables that must exist before the service is allowed to start ─────────────
@ -187,7 +178,6 @@ def sync_role_passwords(conn):
""" """
roles = { roles = {
"grafana_ro": os.getenv("GRAFANA_DB_RO_PASSWORD"), "grafana_ro": os.getenv("GRAFANA_DB_RO_PASSWORD"),
"pgbouncer": os.getenv("PGBOUNCER_AUTH_PASSWORD"),
} }
with conn.cursor() as cur: with conn.cursor() as cur:
for role, password in roles.items(): for role, password in roles.items():
@ -227,7 +217,7 @@ def main():
applied = skipped = 0 applied = skipped = 0
for sql_file in MIGRATIONS: for sql_file in MIGRATIONS:
path = os.path.join("/app", "migrations", sql_file) path = os.path.join("/app", sql_file)
if not os.path.exists(path): if not os.path.exists(path):
print(f" SKIP {sql_file} (file not found in /app)") print(f" SKIP {sql_file} (file not found in /app)")

View file

@ -55,10 +55,10 @@ run_sql -c "
" > /dev/null " > /dev/null
# ── Find and apply pending migrations ──────────────────────────────────────── # ── Find and apply pending migrations ────────────────────────────────────────
MIGRATION_FILES=$(find "$SCRIPT_DIR/migrations" -maxdepth 1 -name '[0-9][0-9]_*.sql' | sort) MIGRATION_FILES=$(find "$SCRIPT_DIR" -maxdepth 1 -name '[0-9][0-9]_*.sql' | sort)
if [[ -z "$MIGRATION_FILES" ]]; then if [[ -z "$MIGRATION_FILES" ]]; then
echo "No migration files found in $SCRIPT_DIR/migrations" echo "No migration files found in $SCRIPT_DIR"
exit 0 exit 0
fi fi

View file

@ -1,88 +0,0 @@
#!/usr/bin/env python3
"""Export OSM POIs (e.g. fuel stations) from a .osm.pbf to GeoJSON + CSV.
These exports feed FleetNow's toggleable map-overlay layers (see
docs/OSM_POI_EXPORT.md and the fleetnow repo's README "Map overlay layers").
No system tooling needed run via uv so pyosmium's prebuilt wheel is fetched:
uv run --no-project --with osmium python scripts/export_osm_pois.py \
kenya-260605.osm.pbf --amenity fuel --brand Shell \
--out-geojson shell_stations.geojson --out-csv shell_stations.csv
Notes:
- Gas stations are OSM ``amenity=fuel``. Brand lives in the ``brand`` tag, but
only ~36% of Kenyan stations carry it, so when ``--brand`` is given and a
feature has no ``brand`` tag we fall back to matching ``name``/``operator``.
- Omit ``--brand`` to export every feature of that amenity.
- Nodes use their own coordinate; ways/areas use the centroid of their nodes
(so ``locations=True`` is required on apply_file).
"""
import argparse, json, csv
def main():
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("pbf", help="input .osm.pbf")
ap.add_argument("--amenity", default="fuel", help="OSM amenity value (default: fuel)")
ap.add_argument("--brand", default=None, help="case-insensitive brand/name match; omit for all")
ap.add_argument("--out-geojson", default="pois.geojson")
ap.add_argument("--out-csv", default="pois.csv")
args = ap.parse_args()
import osmium
brand_lc = args.brand.lower() if args.brand else None
def match(t):
if t.get("amenity") != args.amenity:
return False
if brand_lc is None:
return True
b = (t.get("brand") or "").lower()
if b:
return brand_lc in b
return brand_lc in (t.get("name") or "").lower() or brand_lc in (t.get("operator") or "").lower()
feats = []
def add(lon, lat, t, kind, oid):
feats.append({
"type": "Feature",
"properties": {
"name": t.get("name"), "brand": t.get("brand"),
"operator": t.get("operator"), "osm_type": kind, "osm_id": oid,
},
"geometry": {"type": "Point", "coordinates": [round(lon, 6), round(lat, 6)]},
})
class H(osmium.SimpleHandler):
def node(self, o):
if match(o.tags):
add(o.location.lon, o.location.lat, o.tags, "node", o.id)
def way(self, o):
if match(o.tags):
xs = []; ys = []
for n in o.nodes:
try:
if n.location.valid():
xs.append(n.location.lon); ys.append(n.location.lat)
except Exception:
pass
if xs:
add(sum(xs) / len(xs), sum(ys) / len(ys), o.tags, "way", o.id)
H().apply_file(args.pbf, locations=True)
json.dump({"type": "FeatureCollection", "features": feats}, open(args.out_geojson, "w"))
with open(args.out_csv, "w", newline="") as f:
w = csv.writer(f); w.writerow(["name", "lat", "lon", "brand", "operator", "osm_type", "osm_id"])
for ft in feats:
p = ft["properties"]; lon, lat = ft["geometry"]["coordinates"]
w.writerow([p["name"], lat, lon, p["brand"], p["operator"], p["osm_type"], p["osm_id"]])
print(f"exported {len(feats)} features -> {args.out_geojson}, {args.out_csv}")
if __name__ == "__main__":
main()

View file

@ -1,233 +0,0 @@
name,lat,lon,brand,operator,brand_source,osm_type,osm_id
Shell Kabuagi,-1.316594,36.718419,Shell,,brand_tag,node,30088444
Shell,-1.316337,36.814074,Shell,,brand_tag,node,30092268
Shell,-1.292004,36.784895,Shell,,brand_tag,node,30210342
Shell,-1.292514,36.821731,Shell,,brand_tag,node,30215041
Shell,-1.264944,36.811142,Shell,,brand_tag,node,30402252
Shell Bellevue,-1.321222,36.841704,Shell,,brand_tag,node,30695844
Shell,-1.259212,36.818551,,,name,node,295829498
Shell,-3.400363,38.549144,Shell,,brand_tag,node,344711386
Shell,-4.064245,39.671241,Shell,,brand_tag,node,344969183
Shell,-4.04045,39.678266,Shell,,brand_tag,node,344970554
Shell,-4.035198,39.684952,Shell,,brand_tag,node,344971084
Shell Links Road Filling Station,-4.051857,39.688222,Shell,,brand_tag,node,346562706
Shell,-0.71861,36.432908,Shell,,brand_tag,node,415582755
Shell,-1.307743,36.803669,Shell,,brand_tag,node,490741522
Shell Petrol Station,-1.288024,36.741743,Shell,,brand_tag,node,558923029
Shell,-1.310587,36.817074,Shell,,brand_tag,node,582803761
Shell,-1.305716,36.827261,Shell,,brand_tag,node,582803763
Shell,-1.520877,37.267142,Shell,,brand_tag,node,582803840
Shell Makupa,-4.041392,39.656827,Shell,Shell,brand_tag,node,612947282
Shell Changamwe,-4.027279,39.62732,Shell,Shell,brand_tag,node,612947302
Shell,-1.249864,36.861223,Shell,,brand_tag,node,703562830
Shell,-1.246981,36.871498,Shell,,brand_tag,node,703562919
Shell - Ruiru,-1.149099,36.958483,Shell,,brand_tag,node,711491743
Shell,-1.293773,36.886453,Shell,Shell,brand_tag,node,712868923
Shell,-1.256982,36.922912,Shell,,brand_tag,node,734051667
Shell,-1.230839,36.80343,Shell,Shell,brand_tag,node,812840504
Shell,-1.232602,36.875076,Shell,,brand_tag,node,900302335
Shell Avenue Service Station,-1.285422,36.818863,Shell,,brand_tag,node,911026324
Shell Adams Arcade,-1.300601,36.779709,Shell,,brand_tag,node,1045731889
Shell,-1.267364,36.81745,Shell,,brand_tag,node,1147234418
Shell,-4.085069,39.654867,Shell,Shell,brand_tag,node,1320763086
Shell,0.181801,34.295817,Shell,Indivdual,brand_tag,node,1419926800
Shell,-1.265026,36.740926,Shell,,brand_tag,node,1506606959
Shell,-0.284215,36.068872,Shell,,brand_tag,node,1636429762
Shell,-1.31465,36.859873,Shell,Shell/BP,brand_tag,node,1678061764
Shell,-1.090556,35.871981,Shell,,brand_tag,node,1690703696
Shell,0.03559,37.655216,Shell,,brand_tag,node,1814694405
Shell,0.05734,37.642474,Shell,,brand_tag,node,1814694430
Shell,0.016696,37.077472,Shell,,brand_tag,node,1830086395
Shell,-0.363566,35.293414,Shell,,brand_tag,node,1838955746
Shell,0.634907,34.280633,Shell,,brand_tag,node,1856237414
Shell Bidii,-1.279267,36.848606,Shell,,brand_tag,node,1997615249
Shell,-2.693933,38.166679,Shell,,brand_tag,node,2137912798
Shell Baraka,-1.259949,36.785711,Shell,,brand_tag,node,2218541216
Shell,-4.047937,39.662737,Shell,,brand_tag,node,2377336397
Shell,2.32971,37.988219,Shell,,brand_tag,node,2462468244
Shell,-1.281187,36.816595,Shell,,brand_tag,node,2533881587
Shell,-1.446789,36.968782,Shell,Shell,brand_tag,node,2653484553
Shell Roysambu,-1.217787,36.890669,Shell,,brand_tag,node,2953872784
Shell petrol station,-0.424642,36.952432,,2NK,name,node,3078763165
Shell petrol station,-0.421785,36.952518,,,name,node,3078776472
Shell,-0.334861,37.646147,Shell,,brand_tag,node,3243527416
Isiolo Service Station,0.3519,37.582829,Shell,,brand_tag,node,3247766463
Shell,-0.500952,36.314893,Shell,,brand_tag,node,3421681816
Bajoo Shell Services,1.749142,40.057779,Shell,,brand_tag,node,3683457938
Buna Filling Station,2.786999,39.509127,Shell,,brand_tag,node,3695322660
Shell,-1.395443,36.939718,Shell,,brand_tag,node,3729203207
Shell,-1.10888,36.641976,Shell,,brand_tag,node,3808532767
Shell,-1.299065,36.763624,Shell,,brand_tag,node,4210622090
Shell,-1.245784,36.662797,Shell,,brand_tag,node,4324873067
Shell,0.337182,37.578977,Shell,,brand_tag,node,4461211795
Shell,-3.405215,38.362976,Shell,,brand_tag,node,4475364889
Shell,-0.454161,39.645824,Shell,,brand_tag,node,4685351383
Shell,-0.625556,34.75581,Shell,,brand_tag,node,4720565411
Shell,-0.697715,36.427394,Shell,,brand_tag,node,4914118412
"Shell Petrol Station, Muguga",-1.061481,37.157952,,,name,node,4946660224
"Shell New Thika Rd, Ruiru",-1.160387,36.958055,Shell,,brand_tag,node,4947103423
Shell,-1.226429,36.663491,Shell,,brand_tag,node,4972148621
Shell,-1.229222,36.840393,Shell,,brand_tag,node,5119552023
Shell,-1.264064,36.838234,Shell,,brand_tag,node,5119573528
Shell,-0.977475,37.095977,Shell,,brand_tag,node,5126219526
Shell,-0.929697,37.160111,Shell,,brand_tag,node,5126247329
Shell,-1.011913,36.903025,Shell,,brand_tag,node,5162725223
Shell Petrol Station Kajiado,-1.835716,36.799667,Shell,Shell,brand_tag,node,5179571022
Shell,-1.180887,37.440173,Shell,,brand_tag,node,5181243643
Shell,-1.280736,36.827944,Shell,,brand_tag,node,5217418921
Shell,-1.171399,36.828308,Shell,,brand_tag,node,5327749961
Shell,-1.262778,36.801048,Shell,,brand_tag,node,5340449107
Shell,0.540157,35.296916,Shell,,brand_tag,node,5392739324
Shell,0.448948,35.967056,,,name,node,5403105422
Shell,-1.292007,36.84313,Shell,,brand_tag,node,5496066065
Shell,-1.295157,36.854441,Shell,,brand_tag,node,5496079228
Shell Kasarani Petrol Station,-1.218327,36.895867,,,name,node,5526332569
Shell,-1.30385,36.856284,Shell,,brand_tag,node,5539579719
Shell,-1.195935,36.751887,Shell,,brand_tag,node,5540791550
Shell,-1.3074,36.842468,Shell,,brand_tag,node,5569591300
Shell Banana,-1.175701,36.759722,Shell,,brand_tag,node,5581701614
Shell Kiserian,-1.432004,36.686175,Shell,Vivo,brand_tag,node,5588931919
Mwingi Shell Petrol Station,-0.937425,38.044514,Shell,Shell,brand_tag,node,5768445294
Mart Petrol Station,0.494496,35.746217,Shell,,brand_tag,node,5781632986
Shell,-1.263474,36.981924,Shell,,brand_tag,node,5887135685
Shell,-4.060892,39.662713,Shell,,brand_tag,node,6054282205
Shell,-4.043209,39.663984,Shell,,brand_tag,node,6054858991
Shell,-0.984791,36.584131,Shell,,brand_tag,node,6054861952
Shell,-1.089833,35.882185,Shell,,brand_tag,node,6054877097
Shell,-0.769528,36.501316,Shell,,brand_tag,node,6054980226
Shell,-1.057588,36.776239,,,name,node,6063644317
Shell Filling station,-4.084926,39.654747,Shell,,brand_tag,node,6072960948
Shell,-1.456045,37.004306,Shell,,brand_tag,node,6086991186
Shell,-0.780234,34.948265,Shell,,brand_tag,node,6105930796
Shell,1.01741,35.002629,Shell,,brand_tag,node,6106202680
Shell,-0.929519,37.159777,Shell,,brand_tag,node,6140765579
Shell,-0.074245,37.670579,Shell,,brand_tag,node,6144610331
Shell,0.524964,35.251383,Shell,,brand_tag,node,6147580921
Shell,0.489345,35.269825,Shell,,brand_tag,node,6149443773
Shell Petrol Station,0.465501,35.297389,,,name,node,6149634448
Shell,-1.248207,36.876,Shell,,brand_tag,node,6198796724
Shell,-1.043083,37.066139,Shell,,brand_tag,node,6207691351
Shell,-1.042001,37.071543,Shell,,brand_tag,node,6207707073
Shell,-1.037044,37.071925,Shell,,brand_tag,node,6209964953
Shell,-0.841126,37.137857,,,name,node,6212995383
Shell,-0.485965,37.138349,Shell,,brand_tag,node,6213405879
Shell,-1.347761,36.662815,Shell,,brand_tag,node,6216321668
Shell Petrol Station,-1.416823,36.686915,,,name,node,6218487553
Shell,-1.396852,36.755199,Shell,,brand_tag,node,6218698870
PETRO Shelly,-4.085731,39.667207,,,name,node,6222293185
Shell Maanzoni,-1.516527,37.107005,Shell,,brand_tag,node,6226894926
Shell,-1.532784,37.131763,Shell,,brand_tag,node,6229374240
Shell Kitengela,-1.50442,36.954102,,,name,node,6229505975
shell,-1.735489,37.198837,Shell,,brand_tag,node,6229624406
Shell,-2.081484,37.477328,Shell,,brand_tag,node,6232739137
Shell,-3.973832,39.547043,Shell,,brand_tag,node,6235829860
Shell,-4.007792,39.60037,Shell,,brand_tag,node,6235830590
Shell,0.580828,34.557734,Shell,,brand_tag,node,6236062090
Shell,-1.365272,38.012171,Shell,,brand_tag,node,6236068237
Shell Filling Station,0.035,36.364412,,,name,node,6241664256
Shell Chaka,-0.361651,36.999992,Shell,,brand_tag,node,6244921195
Shell,0.005805,37.072986,Shell,,brand_tag,node,6246803075
Shell,-1.260591,36.710164,Shell,,brand_tag,node,6251561800
Shell service station Fedha,-1.316073,36.895595,Shell,,brand_tag,node,6259798932
Shell Service Station - Kayole,-1.2829,36.90304,Shell,,brand_tag,node,6259810690
Shell Mumias Road,-1.286405,36.88066,Shell,,brand_tag,node,6259860371
Shell,3.094471,35.614012,Shell,,brand_tag,node,6263511612
Shell,0.509984,35.293509,Shell,Shell Petrol Station,brand_tag,node,6327543347
Shell,-0.144338,34.8022,Shell,,brand_tag,node,6633204913
Shell,-0.779415,36.426665,Shell,,brand_tag,node,6644488886
Shell,-3.578128,39.87102,Shell,,brand_tag,node,6716512885
Shell,-3.214362,40.117773,Shell,,brand_tag,node,6793044096
Shell,-1.273195,36.911201,Shell,,brand_tag,node,6819692388
Shell Petrol Station,-1.055007,37.111221,Shell,,brand_tag,node,6851086245
Shell,-0.542158,37.454875,Shell,,brand_tag,node,6860253187
Shell,0.06024,37.636552,Shell,,brand_tag,node,6882011852
Shell,-0.71496,37.261577,Shell,,brand_tag,node,6895782975
shell- Bonje,-3.991998,39.562412,Shell,,brand_tag,node,6938700260
Shell,0.453207,34.130811,Shell,,brand_tag,node,6945529552
Shell,-0.130428,34.794978,Shell,,brand_tag,node,6969176798
Shell,-3.211576,40.121388,Shell,,brand_tag,node,7166621203
Shell,-3.39087,38.581827,Shell,,brand_tag,node,7166621204
shell makupa service station,-4.040825,39.656857,Shell,,brand_tag,node,7172031316
Shell,-0.322371,36.15036,Shell,,brand_tag,node,7187879248
shell,-0.074322,34.682137,Shell,,brand_tag,node,7227297576
Shell,0.28749,34.756277,Shell,,brand_tag,node,7239126633
Shell,-1.323004,36.706266,Shell,,brand_tag,node,7305927852
Shell- Syokimau,-1.357374,36.907769,Shell,,brand_tag,node,7507287888
Shell,-1.210901,36.875751,Shell,Shell,brand_tag,node,7643261185
Shell,-0.973363,37.095865,Shell,,brand_tag,node,7872591802
Shell,-0.366585,35.284074,Shell,,brand_tag,node,7893551877
Shell,0.87809,35.120238,Shell,,brand_tag,node,7934573084
Shell,-1.089807,35.882577,Shell,,brand_tag,node,7988261701
Shell,-0.541871,37.455485,Shell,,brand_tag,node,8039934769
Shell,-1.358313,38.007156,Shell,,brand_tag,node,8047307634
Shell,-3.92977,39.53407,Shell,,brand_tag,node,8050570392
Shell,-0.264808,36.377656,,,name,node,8182514303
Shell Ruai,-1.276187,37.016097,Shell,,brand_tag,node,8202067662
Shell,-1.170384,36.91699,Shell,,brand_tag,node,8231893217
Shell - Eastern By-pass - Ruiru,-1.166976,36.964879,Shell,,brand_tag,node,8247882582
Shell,-1.281858,36.962424,Shell,,brand_tag,node,8293614674
Shell,-1.280476,36.690323,Shell,,brand_tag,node,8318718279
Shell,-1.281238,36.634916,Shell,,brand_tag,node,8321307638
Shell,-1.267623,36.609868,Shell,,brand_tag,node,8321307639
Shell,-1.234142,36.989696,Shell,,brand_tag,node,8338714141
Shell,-1.267493,37.315826,Shell,,brand_tag,node,8338714151
Shell,-1.256284,36.879297,Shell,,brand_tag,node,8345317201
Shell,-1.425451,36.958715,Shell,,brand_tag,node,8371880141
Shell,-0.78364,36.871819,,,name,node,8483709617
Shell,-1.28234,37.104729,Shell,,brand_tag,node,8862700293
Shell,-1.231358,36.924224,Shell,,brand_tag,node,9004506167
Shell Mirema,-1.213808,36.892432,Shell,,brand_tag,node,9014259343
Shell,-1.459477,37.25047,Shell,,brand_tag,node,9028867156
Shell,0.027305,36.365863,Shell,,brand_tag,node,9048281880
Shell,-0.20372,35.843587,Shell,,brand_tag,node,9053460332
Shell,-1.229246,36.84025,Shell,,brand_tag,node,10080456017
Shell,-3.936283,39.744896,,,name,node,10255650224
Shell Petrol Station,-1.286734,36.740804,,,name,node,10971302670
Shell -Bombolulu,-4.025633,39.697377,Shell,,brand_tag,node,11500364389
Shell,-1.313698,36.720914,Shell,,brand_tag,node,11711795482
Shell,-1.274671,36.799912,Shell,,brand_tag,node,12163148139
Shell,-1.307959,36.781587,Shell,,brand_tag,node,12165032865
Shell,0.28095,34.744859,Shell,,brand_tag,node,12489868997
Shell Syokimau,-1.378091,36.927818,,,name,node,12600151901
Shell,-1.262862,36.90678,,,name,node,12886546509
Shell Gas Station,-0.779732,36.427412,,,name,node,13088820396
Shell,-1.230649,34.482215,Shell,,brand_tag,node,13446964574
Shell,-0.900865,34.53639,Shell,,brand_tag,node,13446964578
Shell,0.078482,34.720706,Shell,,brand_tag,node,13447042942
Shell,0.600804,35.163178,Shell,,brand_tag,node,13528448115
shell,-0.143442,34.801363,,,name,node,13714210044
shell,-0.077947,34.727069,Shell,,brand_tag,node,13720608494
Shell,-1.282701,36.824838,Shell,,brand_tag,way,123365084
Shell,-1.2799,36.82273,Shell,,brand_tag,way,125107079
Shell,-1.289727,36.811096,Shell,,brand_tag,way,125336232
Shell,-1.287955,36.838738,Shell,,brand_tag,way,126936993
Shell,-1.272506,36.83183,Shell,,brand_tag,way,126995763
Shell Service Station - Jogoo Road,-1.295715,36.860244,Shell,,brand_tag,way,129323643
Shell,-1.268949,36.817225,Shell,,brand_tag,way,133548150
Shell,-1.310807,36.817766,Shell,,brand_tag,way,144188726
Shell- Lavington,-1.280811,36.769286,Shell,Shell,brand_tag,way,226322138
Shell,-1.322412,36.708022,Shell,,brand_tag,way,226714111
Shell,-1.263021,36.802726,Shell,,brand_tag,way,238857325
Shell,-1.30349,36.828502,Shell,,brand_tag,way,366568545
Shell,-0.09443,34.76444,Shell,,brand_tag,way,390104534
Shell,-0.282248,36.09429,Shell,,brand_tag,way,483211211
Shell,-0.285481,36.075122,Shell,,brand_tag,way,488459901
Shell Kitengela ex-Engen,-1.491085,36.954337,Shell,,brand_tag,way,536796727
Shell Voi,-3.400372,38.549126,Shell,Shell,brand_tag,way,593734920
Shell,-0.865417,36.566545,,,name,way,642076596
Shell,-1.275817,36.834388,Shell,,brand_tag,way,686179946
Shell,-0.536827,37.452256,Shell,,brand_tag,way,732602668
Shell Petrol Station - Greenspan,-1.288893,36.902407,Shell,,brand_tag,way,977833647
Shell petrol station (feroze),-1.26303,36.906097,Shell,,brand_tag,way,1055608664
Shell,-0.268103,34.971231,Shell,,brand_tag,way,1069555494
Shell Hurlingham,-1.295405,36.799606,Shell,,brand_tag,way,1088482284
Shell Service Station - Embakassi,-1.317926,36.917619,Shell,,brand_tag,way,1107378445
Shell,-1.328958,36.683097,Shell,,brand_tag,way,1107729725
Shell,-2.831336,37.524927,Shell,,brand_tag,way,1110216588
Shell Kahawa Sukari,-1.188788,36.931934,Shell,,brand_tag,way,1135425767
Shell,-0.074421,34.691528,Shell,,brand_tag,way,1222533725
Shell Service Station - Likoni Road,-1.303854,36.856227,Shell,,brand_tag,way,1273152921
Shell,-1.835509,36.799548,Shell,,brand_tag,way,1290701573
Shell,-2.538055,36.800975,Shell,,brand_tag,way,1413265354
Shell Fuel Station - Tala,-1.26749,37.315706,,,name,way,1434009884
Shell,-1.266132,36.98704,Shell,Shell,brand_tag,way,1497383075
1 name lat lon brand operator brand_source osm_type osm_id
2 Shell Kabuagi -1.316594 36.718419 Shell brand_tag node 30088444
3 Shell -1.316337 36.814074 Shell brand_tag node 30092268
4 Shell -1.292004 36.784895 Shell brand_tag node 30210342
5 Shell -1.292514 36.821731 Shell brand_tag node 30215041
6 Shell -1.264944 36.811142 Shell brand_tag node 30402252
7 Shell Bellevue -1.321222 36.841704 Shell brand_tag node 30695844
8 Shell -1.259212 36.818551 name node 295829498
9 Shell -3.400363 38.549144 Shell brand_tag node 344711386
10 Shell -4.064245 39.671241 Shell brand_tag node 344969183
11 Shell -4.04045 39.678266 Shell brand_tag node 344970554
12 Shell -4.035198 39.684952 Shell brand_tag node 344971084
13 Shell Links Road Filling Station -4.051857 39.688222 Shell brand_tag node 346562706
14 Shell -0.71861 36.432908 Shell brand_tag node 415582755
15 Shell -1.307743 36.803669 Shell brand_tag node 490741522
16 Shell Petrol Station -1.288024 36.741743 Shell brand_tag node 558923029
17 Shell -1.310587 36.817074 Shell brand_tag node 582803761
18 Shell -1.305716 36.827261 Shell brand_tag node 582803763
19 Shell -1.520877 37.267142 Shell brand_tag node 582803840
20 Shell Makupa -4.041392 39.656827 Shell Shell brand_tag node 612947282
21 Shell Changamwe -4.027279 39.62732 Shell Shell brand_tag node 612947302
22 Shell -1.249864 36.861223 Shell brand_tag node 703562830
23 Shell -1.246981 36.871498 Shell brand_tag node 703562919
24 Shell - Ruiru -1.149099 36.958483 Shell brand_tag node 711491743
25 Shell -1.293773 36.886453 Shell Shell brand_tag node 712868923
26 Shell -1.256982 36.922912 Shell brand_tag node 734051667
27 Shell -1.230839 36.80343 Shell Shell brand_tag node 812840504
28 Shell -1.232602 36.875076 Shell brand_tag node 900302335
29 Shell Avenue Service Station -1.285422 36.818863 Shell brand_tag node 911026324
30 Shell Adams Arcade -1.300601 36.779709 Shell brand_tag node 1045731889
31 Shell -1.267364 36.81745 Shell brand_tag node 1147234418
32 Shell -4.085069 39.654867 Shell Shell brand_tag node 1320763086
33 Shell 0.181801 34.295817 Shell Indivdual brand_tag node 1419926800
34 Shell -1.265026 36.740926 Shell brand_tag node 1506606959
35 Shell -0.284215 36.068872 Shell brand_tag node 1636429762
36 Shell -1.31465 36.859873 Shell Shell/BP brand_tag node 1678061764
37 Shell -1.090556 35.871981 Shell brand_tag node 1690703696
38 Shell 0.03559 37.655216 Shell brand_tag node 1814694405
39 Shell 0.05734 37.642474 Shell brand_tag node 1814694430
40 Shell 0.016696 37.077472 Shell brand_tag node 1830086395
41 Shell -0.363566 35.293414 Shell brand_tag node 1838955746
42 Shell 0.634907 34.280633 Shell brand_tag node 1856237414
43 Shell Bidii -1.279267 36.848606 Shell brand_tag node 1997615249
44 Shell -2.693933 38.166679 Shell brand_tag node 2137912798
45 Shell Baraka -1.259949 36.785711 Shell brand_tag node 2218541216
46 Shell -4.047937 39.662737 Shell brand_tag node 2377336397
47 Shell 2.32971 37.988219 Shell brand_tag node 2462468244
48 Shell -1.281187 36.816595 Shell brand_tag node 2533881587
49 Shell -1.446789 36.968782 Shell Shell brand_tag node 2653484553
50 Shell Roysambu -1.217787 36.890669 Shell brand_tag node 2953872784
51 Shell petrol station -0.424642 36.952432 2NK name node 3078763165
52 Shell petrol station -0.421785 36.952518 name node 3078776472
53 Shell -0.334861 37.646147 Shell brand_tag node 3243527416
54 Isiolo Service Station 0.3519 37.582829 Shell brand_tag node 3247766463
55 Shell -0.500952 36.314893 Shell brand_tag node 3421681816
56 Bajoo Shell Services 1.749142 40.057779 Shell brand_tag node 3683457938
57 Buna Filling Station 2.786999 39.509127 Shell brand_tag node 3695322660
58 Shell -1.395443 36.939718 Shell brand_tag node 3729203207
59 Shell -1.10888 36.641976 Shell brand_tag node 3808532767
60 Shell -1.299065 36.763624 Shell brand_tag node 4210622090
61 Shell -1.245784 36.662797 Shell brand_tag node 4324873067
62 Shell 0.337182 37.578977 Shell brand_tag node 4461211795
63 Shell -3.405215 38.362976 Shell brand_tag node 4475364889
64 Shell -0.454161 39.645824 Shell brand_tag node 4685351383
65 Shell -0.625556 34.75581 Shell brand_tag node 4720565411
66 Shell -0.697715 36.427394 Shell brand_tag node 4914118412
67 Shell Petrol Station, Muguga -1.061481 37.157952 name node 4946660224
68 Shell New Thika Rd, Ruiru -1.160387 36.958055 Shell brand_tag node 4947103423
69 Shell -1.226429 36.663491 Shell brand_tag node 4972148621
70 Shell -1.229222 36.840393 Shell brand_tag node 5119552023
71 Shell -1.264064 36.838234 Shell brand_tag node 5119573528
72 Shell -0.977475 37.095977 Shell brand_tag node 5126219526
73 Shell -0.929697 37.160111 Shell brand_tag node 5126247329
74 Shell -1.011913 36.903025 Shell brand_tag node 5162725223
75 Shell Petrol Station Kajiado -1.835716 36.799667 Shell Shell brand_tag node 5179571022
76 Shell -1.180887 37.440173 Shell brand_tag node 5181243643
77 Shell -1.280736 36.827944 Shell brand_tag node 5217418921
78 Shell -1.171399 36.828308 Shell brand_tag node 5327749961
79 Shell -1.262778 36.801048 Shell brand_tag node 5340449107
80 Shell 0.540157 35.296916 Shell brand_tag node 5392739324
81 Shell 0.448948 35.967056 name node 5403105422
82 Shell -1.292007 36.84313 Shell brand_tag node 5496066065
83 Shell -1.295157 36.854441 Shell brand_tag node 5496079228
84 Shell Kasarani Petrol Station -1.218327 36.895867 name node 5526332569
85 Shell -1.30385 36.856284 Shell brand_tag node 5539579719
86 Shell -1.195935 36.751887 Shell brand_tag node 5540791550
87 Shell -1.3074 36.842468 Shell brand_tag node 5569591300
88 Shell Banana -1.175701 36.759722 Shell brand_tag node 5581701614
89 Shell Kiserian -1.432004 36.686175 Shell Vivo brand_tag node 5588931919
90 Mwingi Shell Petrol Station -0.937425 38.044514 Shell Shell brand_tag node 5768445294
91 Mart Petrol Station 0.494496 35.746217 Shell brand_tag node 5781632986
92 Shell -1.263474 36.981924 Shell brand_tag node 5887135685
93 Shell -4.060892 39.662713 Shell brand_tag node 6054282205
94 Shell -4.043209 39.663984 Shell brand_tag node 6054858991
95 Shell -0.984791 36.584131 Shell brand_tag node 6054861952
96 Shell -1.089833 35.882185 Shell brand_tag node 6054877097
97 Shell -0.769528 36.501316 Shell brand_tag node 6054980226
98 Shell -1.057588 36.776239 name node 6063644317
99 Shell Filling station -4.084926 39.654747 Shell brand_tag node 6072960948
100 Shell -1.456045 37.004306 Shell brand_tag node 6086991186
101 Shell -0.780234 34.948265 Shell brand_tag node 6105930796
102 Shell 1.01741 35.002629 Shell brand_tag node 6106202680
103 Shell -0.929519 37.159777 Shell brand_tag node 6140765579
104 Shell -0.074245 37.670579 Shell brand_tag node 6144610331
105 Shell 0.524964 35.251383 Shell brand_tag node 6147580921
106 Shell 0.489345 35.269825 Shell brand_tag node 6149443773
107 Shell Petrol Station 0.465501 35.297389 name node 6149634448
108 Shell -1.248207 36.876 Shell brand_tag node 6198796724
109 Shell -1.043083 37.066139 Shell brand_tag node 6207691351
110 Shell -1.042001 37.071543 Shell brand_tag node 6207707073
111 Shell -1.037044 37.071925 Shell brand_tag node 6209964953
112 Shell -0.841126 37.137857 name node 6212995383
113 Shell -0.485965 37.138349 Shell brand_tag node 6213405879
114 Shell -1.347761 36.662815 Shell brand_tag node 6216321668
115 Shell Petrol Station -1.416823 36.686915 name node 6218487553
116 Shell -1.396852 36.755199 Shell brand_tag node 6218698870
117 PETRO Shelly -4.085731 39.667207 name node 6222293185
118 Shell Maanzoni -1.516527 37.107005 Shell brand_tag node 6226894926
119 Shell -1.532784 37.131763 Shell brand_tag node 6229374240
120 Shell Kitengela -1.50442 36.954102 name node 6229505975
121 shell -1.735489 37.198837 Shell brand_tag node 6229624406
122 Shell -2.081484 37.477328 Shell brand_tag node 6232739137
123 Shell -3.973832 39.547043 Shell brand_tag node 6235829860
124 Shell -4.007792 39.60037 Shell brand_tag node 6235830590
125 Shell 0.580828 34.557734 Shell brand_tag node 6236062090
126 Shell -1.365272 38.012171 Shell brand_tag node 6236068237
127 Shell Filling Station 0.035 36.364412 name node 6241664256
128 Shell Chaka -0.361651 36.999992 Shell brand_tag node 6244921195
129 Shell 0.005805 37.072986 Shell brand_tag node 6246803075
130 Shell -1.260591 36.710164 Shell brand_tag node 6251561800
131 Shell service station Fedha -1.316073 36.895595 Shell brand_tag node 6259798932
132 Shell Service Station - Kayole -1.2829 36.90304 Shell brand_tag node 6259810690
133 Shell Mumias Road -1.286405 36.88066 Shell brand_tag node 6259860371
134 Shell 3.094471 35.614012 Shell brand_tag node 6263511612
135 Shell 0.509984 35.293509 Shell Shell Petrol Station brand_tag node 6327543347
136 Shell -0.144338 34.8022 Shell brand_tag node 6633204913
137 Shell -0.779415 36.426665 Shell brand_tag node 6644488886
138 Shell -3.578128 39.87102 Shell brand_tag node 6716512885
139 Shell -3.214362 40.117773 Shell brand_tag node 6793044096
140 Shell -1.273195 36.911201 Shell brand_tag node 6819692388
141 Shell Petrol Station -1.055007 37.111221 Shell brand_tag node 6851086245
142 Shell -0.542158 37.454875 Shell brand_tag node 6860253187
143 Shell 0.06024 37.636552 Shell brand_tag node 6882011852
144 Shell -0.71496 37.261577 Shell brand_tag node 6895782975
145 shell- Bonje -3.991998 39.562412 Shell brand_tag node 6938700260
146 Shell 0.453207 34.130811 Shell brand_tag node 6945529552
147 Shell -0.130428 34.794978 Shell brand_tag node 6969176798
148 Shell -3.211576 40.121388 Shell brand_tag node 7166621203
149 Shell -3.39087 38.581827 Shell brand_tag node 7166621204
150 shell makupa service station -4.040825 39.656857 Shell brand_tag node 7172031316
151 Shell -0.322371 36.15036 Shell brand_tag node 7187879248
152 shell -0.074322 34.682137 Shell brand_tag node 7227297576
153 Shell 0.28749 34.756277 Shell brand_tag node 7239126633
154 Shell -1.323004 36.706266 Shell brand_tag node 7305927852
155 Shell- Syokimau -1.357374 36.907769 Shell brand_tag node 7507287888
156 Shell -1.210901 36.875751 Shell Shell brand_tag node 7643261185
157 Shell -0.973363 37.095865 Shell brand_tag node 7872591802
158 Shell -0.366585 35.284074 Shell brand_tag node 7893551877
159 Shell 0.87809 35.120238 Shell brand_tag node 7934573084
160 Shell -1.089807 35.882577 Shell brand_tag node 7988261701
161 Shell -0.541871 37.455485 Shell brand_tag node 8039934769
162 Shell -1.358313 38.007156 Shell brand_tag node 8047307634
163 Shell -3.92977 39.53407 Shell brand_tag node 8050570392
164 Shell -0.264808 36.377656 name node 8182514303
165 Shell Ruai -1.276187 37.016097 Shell brand_tag node 8202067662
166 Shell -1.170384 36.91699 Shell brand_tag node 8231893217
167 Shell - Eastern By-pass - Ruiru -1.166976 36.964879 Shell brand_tag node 8247882582
168 Shell -1.281858 36.962424 Shell brand_tag node 8293614674
169 Shell -1.280476 36.690323 Shell brand_tag node 8318718279
170 Shell -1.281238 36.634916 Shell brand_tag node 8321307638
171 Shell -1.267623 36.609868 Shell brand_tag node 8321307639
172 Shell -1.234142 36.989696 Shell brand_tag node 8338714141
173 Shell -1.267493 37.315826 Shell brand_tag node 8338714151
174 Shell -1.256284 36.879297 Shell brand_tag node 8345317201
175 Shell -1.425451 36.958715 Shell brand_tag node 8371880141
176 Shell -0.78364 36.871819 name node 8483709617
177 Shell -1.28234 37.104729 Shell brand_tag node 8862700293
178 Shell -1.231358 36.924224 Shell brand_tag node 9004506167
179 Shell Mirema -1.213808 36.892432 Shell brand_tag node 9014259343
180 Shell -1.459477 37.25047 Shell brand_tag node 9028867156
181 Shell 0.027305 36.365863 Shell brand_tag node 9048281880
182 Shell -0.20372 35.843587 Shell brand_tag node 9053460332
183 Shell -1.229246 36.84025 Shell brand_tag node 10080456017
184 Shell -3.936283 39.744896 name node 10255650224
185 Shell Petrol Station -1.286734 36.740804 name node 10971302670
186 Shell -Bombolulu -4.025633 39.697377 Shell brand_tag node 11500364389
187 Shell -1.313698 36.720914 Shell brand_tag node 11711795482
188 Shell -1.274671 36.799912 Shell brand_tag node 12163148139
189 Shell -1.307959 36.781587 Shell brand_tag node 12165032865
190 Shell 0.28095 34.744859 Shell brand_tag node 12489868997
191 Shell Syokimau -1.378091 36.927818 name node 12600151901
192 Shell -1.262862 36.90678 name node 12886546509
193 Shell Gas Station -0.779732 36.427412 name node 13088820396
194 Shell -1.230649 34.482215 Shell brand_tag node 13446964574
195 Shell -0.900865 34.53639 Shell brand_tag node 13446964578
196 Shell 0.078482 34.720706 Shell brand_tag node 13447042942
197 Shell 0.600804 35.163178 Shell brand_tag node 13528448115
198 shell -0.143442 34.801363 name node 13714210044
199 shell -0.077947 34.727069 Shell brand_tag node 13720608494
200 Shell -1.282701 36.824838 Shell brand_tag way 123365084
201 Shell -1.2799 36.82273 Shell brand_tag way 125107079
202 Shell -1.289727 36.811096 Shell brand_tag way 125336232
203 Shell -1.287955 36.838738 Shell brand_tag way 126936993
204 Shell -1.272506 36.83183 Shell brand_tag way 126995763
205 Shell Service Station - Jogoo Road -1.295715 36.860244 Shell brand_tag way 129323643
206 Shell -1.268949 36.817225 Shell brand_tag way 133548150
207 Shell -1.310807 36.817766 Shell brand_tag way 144188726
208 Shell- Lavington -1.280811 36.769286 Shell Shell brand_tag way 226322138
209 Shell -1.322412 36.708022 Shell brand_tag way 226714111
210 Shell -1.263021 36.802726 Shell brand_tag way 238857325
211 Shell -1.30349 36.828502 Shell brand_tag way 366568545
212 Shell -0.09443 34.76444 Shell brand_tag way 390104534
213 Shell -0.282248 36.09429 Shell brand_tag way 483211211
214 Shell -0.285481 36.075122 Shell brand_tag way 488459901
215 Shell Kitengela ex-Engen -1.491085 36.954337 Shell brand_tag way 536796727
216 Shell Voi -3.400372 38.549126 Shell Shell brand_tag way 593734920
217 Shell -0.865417 36.566545 name way 642076596
218 Shell -1.275817 36.834388 Shell brand_tag way 686179946
219 Shell -0.536827 37.452256 Shell brand_tag way 732602668
220 Shell Petrol Station - Greenspan -1.288893 36.902407 Shell brand_tag way 977833647
221 Shell petrol station (feroze) -1.26303 36.906097 Shell brand_tag way 1055608664
222 Shell -0.268103 34.971231 Shell brand_tag way 1069555494
223 Shell Hurlingham -1.295405 36.799606 Shell brand_tag way 1088482284
224 Shell Service Station - Embakassi -1.317926 36.917619 Shell brand_tag way 1107378445
225 Shell -1.328958 36.683097 Shell brand_tag way 1107729725
226 Shell -2.831336 37.524927 Shell brand_tag way 1110216588
227 Shell Kahawa Sukari -1.188788 36.931934 Shell brand_tag way 1135425767
228 Shell -0.074421 34.691528 Shell brand_tag way 1222533725
229 Shell Service Station - Likoni Road -1.303854 36.856227 Shell brand_tag way 1273152921
230 Shell -1.835509 36.799548 Shell brand_tag way 1290701573
231 Shell -2.538055 36.800975 Shell brand_tag way 1413265354
232 Shell Fuel Station - Tala -1.26749 37.315706 name way 1434009884
233 Shell -1.266132 36.98704 Shell Shell brand_tag way 1497383075

File diff suppressed because one or more lines are too long

View file

@ -108,7 +108,7 @@ WEBHOOK_ALARM_NULL_TYPE = {
"gateTime": "2024-04-12 07:30:00", "gateTime": "2024-04-12 07:30:00",
} }
# Alarm with no lat/lng — cross-feed (FIX-M21) must skip live_positions # Alarm with no lat/lng — cross-feed (FIX-M20) must skip live_positions
# but still write the alarm row. # but still write the alarm row.
WEBHOOK_ALARM_NO_POSITION = { WEBHOOK_ALARM_NO_POSITION = {
"deviceImei": "123456789012345", "deviceImei": "123456789012345",

View file

@ -99,7 +99,7 @@ class TestPushAlarm:
assert response.json()["code"] == 0 assert response.json()["code"] == 0
def test_alarm_cross_feeds_live_position(self, client, mock_db): def test_alarm_cross_feeds_live_position(self, client, mock_db):
"""FIX-M21: a valid alarm must additionally upsert live_positions.""" """FIX-M20: a valid alarm must additionally upsert live_positions."""
mock_conn, mock_cur = mock_db mock_conn, mock_cur = mock_db
data_list = json.dumps([WEBHOOK_ALARM_PAYLOAD]) data_list = json.dumps([WEBHOOK_ALARM_PAYLOAD])
response = client.post("/pushalarm", data={"token": "", "data_list": data_list}) response = client.post("/pushalarm", data={"token": "", "data_list": data_list})
@ -112,7 +112,7 @@ class TestPushAlarm:
assert len(lp_inserts) == 1, "Cross-feed must upsert live_positions exactly once" assert len(lp_inserts) == 1, "Cross-feed must upsert live_positions exactly once"
def test_alarm_without_lat_lng_skips_cross_feed(self, client, mock_db): def test_alarm_without_lat_lng_skips_cross_feed(self, client, mock_db):
"""FIX-M21: an alarm without lat/lng must NOT touch live_positions """FIX-M20: an alarm without lat/lng must NOT touch live_positions
(but must still insert the alarm row).""" (but must still insert the alarm row)."""
mock_conn, mock_cur = mock_db mock_conn, mock_cur = mock_db
data_list = json.dumps([WEBHOOK_ALARM_NO_POSITION]) data_list = json.dumps([WEBHOOK_ALARM_NO_POSITION])
@ -130,7 +130,7 @@ class TestPushAlarm:
assert len(alarm_inserts) == 1, "Alarm row must still write" assert len(alarm_inserts) == 1, "Alarm row must still write"
def test_alarm_with_zero_island_skips_cross_feed(self, client, mock_db): def test_alarm_with_zero_island_skips_cross_feed(self, client, mock_db):
"""FIX-M21: a (0, 0) fix must NOT propagate to live_positions — """FIX-M20: a (0, 0) fix must NOT propagate to live_positions —
is_valid_fix in the shared helper guards Zero Island.""" is_valid_fix in the shared helper guards Zero Island."""
mock_conn, mock_cur = mock_db mock_conn, mock_cur = mock_db
data_list = json.dumps([WEBHOOK_ALARM_ZERO_ISLAND]) data_list = json.dumps([WEBHOOK_ALARM_ZERO_ISLAND])

View file

@ -1,4 +1,4 @@
"""Unit tests for the FIX-M21 stale-IMEI recovery helpers. """Unit tests for the FIX-M20 stale-IMEI recovery helpers.
Covers: Covers:
- ts_shared_rev.get_stale_imeis the SQL selector - ts_shared_rev.get_stale_imeis the SQL selector

View file

@ -220,9 +220,9 @@ SELECT
current_mileage, current_mileage,
satellite satellite
FROM tracksolid.position_history FROM tracksolid.position_history
WHERE imei = '862798052708167' WHERE imei = 'YOUR_IMEI_HERE'
AND gps_time >= '2026-04-22 00:00:00+03' AND gps_time >= '2026-04-10 00:00:00+03'
AND gps_time < '2026-04-23 00:00:00+03' AND gps_time < '2026-04-11 00:00:00+03'
ORDER BY gps_time ASC; ORDER BY gps_time ASC;
``` ```

View file

@ -24,11 +24,9 @@ import logging
import os import os
import signal import signal
import sys import sys
import threading
import time import time
from contextlib import contextmanager from contextlib import contextmanager
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
from functools import lru_cache
from typing import Optional, Any from typing import Optional, Any
import psycopg2 import psycopg2
@ -238,7 +236,7 @@ def get_active_imeis() -> list[str]:
return [r[0] for r in cur.fetchall()] return [r[0] for r in cur.fetchall()]
def get_stale_imeis(stale_minutes: int = 30) -> list[str]: def get_stale_imeis(stale_minutes: int = 30) -> list[str]:
"""[FIX-M21] IMEIs whose live_positions fix is missing or older than N minutes. """[FIX-M20] IMEIs whose live_positions fix is missing or older than N minutes.
Used by poll_stale_locations() to feed get_device_locations() with the Used by poll_stale_locations() to feed get_device_locations() with the
set the 60s sweep silently dropped. Ordered oldest-first (NULLs first) set the 60s sweep silently dropped. Ordered oldest-first (NULLs first)
@ -258,7 +256,7 @@ def get_stale_imeis(stale_minutes: int = 30) -> list[str]:
return [r[0] for r in cur.fetchall()] return [r[0] for r in cur.fetchall()]
def ensure_device(cur, imei: str, device_name: Optional[str] = None) -> None: def ensure_device(cur, imei: str, device_name: Optional[str] = None) -> None:
"""[FIX-M21] Upsert a stub row into tracksolid.devices so FK-constrained """[FIX-M20] Upsert a stub row into tracksolid.devices so FK-constrained
inserts don't fail when ingest paths see an IMEI before sync_devices does. inserts don't fail when ingest paths see an IMEI before sync_devices does.
Lifted out of webhook_receiver_rev.py to be shareable by every writer Lifted out of webhook_receiver_rev.py to be shareable by every writer
@ -285,7 +283,7 @@ def upsert_live_position(
current_mileage=None, current_mileage=None,
extras: Optional[dict] = None, extras: Optional[dict] = None,
) -> int: ) -> int:
"""[FIX-M21] Time-guarded upsert into tracksolid.live_positions. """[FIX-M20] Time-guarded upsert into tracksolid.live_positions.
Only overwrites the stored row when the incoming gps_time is strictly Only overwrites the stored row when the incoming gps_time is strictly
newer than what's already there. NULL stored gps_time always loses newer than what's already there. NULL stored gps_time always loses
@ -444,81 +442,3 @@ def _update_token_cache(r: dict) -> str:
""", (USER_ID, token, r.get("refreshToken"), expires_at)) """, (USER_ID, token, r.get("refreshToken"), expires_at))
conn.commit() conn.commit()
return token return token
# ── Reverse Geocoding (Nominatim) ────────────────────────────────────────────
# Best-effort lookup used by poll_trips() to populate trips.start_address /
# end_address. Must NEVER raise — failure returns None and the trip insert
# proceeds without the address.
_NOMINATIM_URL = os.getenv(
"NOMINATIM_URL",
"https://nominatim.openstreetmap.org/reverse",
)
_NOMINATIM_USER_AGENT = os.getenv(
"NOMINATIM_USER_AGENT",
"fireside-tracksolid/1.0 (kianiadee@gmail.com)",
)
_GEOCODE_LOCK = threading.Lock()
_GEOCODE_LAST_CALL_AT: float = 0.0
_GEOCODE_MIN_INTERVAL_S: float = 1.0 # Nominatim TOS — 1 req/sec absolute max
def _geocode_throttle() -> None:
"""Sleep just long enough since the previous call to honour 1 req/sec."""
global _GEOCODE_LAST_CALL_AT
with _GEOCODE_LOCK:
elapsed = time.monotonic() - _GEOCODE_LAST_CALL_AT
if elapsed < _GEOCODE_MIN_INTERVAL_S:
time.sleep(_GEOCODE_MIN_INTERVAL_S - elapsed)
_GEOCODE_LAST_CALL_AT = time.monotonic()
@lru_cache(maxsize=2048)
def _reverse_geocode_cached(lat_round: float, lng_round: float) -> Optional[str]:
"""Cached HTTP call. Key is lat/lng rounded to 4 dp (~11 m precision)."""
_geocode_throttle()
try:
r = _session.get(
_NOMINATIM_URL,
params={
"lat": lat_round,
"lon": lng_round,
"format": "json",
"zoom": 18,
"addressdetails": 0,
},
headers={"User-Agent": _NOMINATIM_USER_AGENT},
timeout=10,
)
r.raise_for_status()
data = r.json()
addr = data.get("display_name")
if addr:
return addr.strip()
return None
except (requests.RequestException, ValueError) as e:
_log.warning("reverse_geocode failed lat=%s lng=%s: %s",
lat_round, lng_round, e)
return None
def reverse_geocode(lat: Any, lng: Any) -> Optional[str]:
"""
Reverse-geocode a coordinate to a human-readable address via Nominatim.
Best-effort. Never raises. Returns None on:
missing / invalid lat or lng
HTTP/timeout/JSON failure
Nominatim returns no display_name
Cached on lat/lng rounded to 4 decimal places (~11 m), which keeps
repeated visits to the same depot/site from re-querying.
"""
flat, flng = clean_num(lat), clean_num(lng)
if flat is None or flng is None:
return None
if flat == 0.0 and flng == 0.0:
return None
if not (-90 <= flat <= 90 and -180 <= flng <= 180):
return None
return _reverse_geocode_cached(round(flat, 4), round(flng, 4))

View file

@ -384,7 +384,7 @@ async def push_alarm(request: Request):
clean_num(item.get("speed")), clean_num(item.get("speed")),
)) ))
# [FIX-M21] Cross-feed: every Jimi alarm carries lat/lng. # [FIX-M20] Cross-feed: every Jimi alarm carries lat/lng.
# Refresh live_positions so dashboard markers don't have to # Refresh live_positions so dashboard markers don't have to
# wait up to 60s for the next polled sweep. Time-guarded # wait up to 60s for the next polled sweep. Time-guarded
# inside the helper — alarms older than the current fix lose. # inside the helper — alarms older than the current fix lose.