On‑Truck System Architecture — ArcGIS / QGIS Integration

Compiled 2025-11-01. Black‑on‑white, print‑friendly. Links point to primary docs where possible.

This document describes a practical, offline‑first architecture to integrate an on‑truck edge stack with either ArcGIS (ArcGIS Online/Enterprise) or QGIS (PostGIS/QGIS Server/QField/Mergin). It covers components, data flow, schemas, sync patterns, security, and example payloads.

1) Overview

The edge device (Pi‑5/Jetson) hosts sensors, a lightweight message broker (MQTT), a geofence engine, and a sync worker. It renders offline maps (tiles) for the driver tablet and publishes events (points + media) to GIS. The architecture is dual‑path so you can deploy either ArcGIS‑first or QGIS‑first without re‑wiring sensors.

2) Components

3) Data flow (ASCII diagrams)

3A) Common on‑truck flow

[Sensors: camera, GNSS, temp/TVOC, etc.]
         │
     (MQTT topics)
         │
 [Edge Geo‑Service] ──► writes ► [GeoPackage (local)] + [Outbox (SQLite)]
         │                                 │
         │                                 └─► [Offline tiles (MBTiles)] for cab map
         └─► [Geofence engine] compares GNSS to local polygons (schools/noise zones)
  

3B) ArcGIS‑first (ArcGIS Online/Enterprise)

[Outbox] ─(batch/secure HTTPS)─► [ArcGIS Feature Service (points/lines)]
                      └─────────► [ArcGIS Add Attachment] (images/video)
                                    ▲
                      [Field Maps] ◄─┴─ syncs offline areas + shows events
  

3C) QGIS‑first (PostGIS / QGIS Server)

[Outbox] ─(batch/HTTPS)─► [Sync API] ─► [PostGIS]
                                 └──► [Object store] (S3) for media
        QField (tablet) ◄──── WFS‑T / Mergin sync ───► PostGIS
  

4) Feature schemas

Use normalized layers with small, stable fields. Store heavy media as attachments/objects; keep only URLs in features.

4A) truck_events (point)

FieldTypeExampleNotes
event_idGUID/String6f8c…Edge‑generated UUID.
ts_utcDatetime2025‑10‑01T13:22:06ZISO‑8601.
route_idStringR‑12ARoute/day key.
event_typeStringcontam_flagSee taxonomy below.
severityShort20–3.
lat, lonDouble25.774,‑80.193WGS84.
azimuthShort182Vehicle heading.
image_url / attach_idString…/img/abc.jpgURL (QGIS) or Attachment Id (ArcGIS).
notesText“Plastic bag in organics”Short free text.

4B) truck_tracks (line or point‑time series)

Taxonomy (examples)

5) Sync & offline

  1. Local cache: write all edits/events to GeoPackage and an outbox (SQLite) with retry metadata.
  2. Batching: flush every N events or M seconds; compact large payloads.
  3. Conflict strategy: edge is append‑only; server resolves by event_id uniqueness.
  4. Offline maps: ArcGIS: prepare Offline Areas in Field Maps (MMPK/VTPK). QGIS: use MBTiles/GeoPackage tiles.
  5. Attachments: ArcGIS: Add Attachment API. QGIS: upload to object store; save URL in feature.

6) Security & privacy

7) Performance & reliability (targets)

8) API examples

8A) ArcGIS — Add Features (REST)

POST https://services.arcgis.com/<orgid>/arcgis/rest/services/truck_events/FeatureServer/0/addFeatures
Content-Type: application/x-www-form-urlencoded
f=json&token=<ACCESS_TOKEN>&features=[{
  "attributes": {
    "event_id":"6f8c9…","ts_utc":1730409726,"route_id":"R-12A","event_type":"contam_flag","severity":2
  },
  "geometry": {"x": -122.3352,"y": 47.6080,"spatialReference":{"wkid":4326}}
}]
  

8B) ArcGIS — Add Attachment

POST .../FeatureServer/0/{objectId}/addAttachment
Headers: Authorization: Bearer <ACCESS_TOKEN>
Form-Data: attachment=@frame_2025-11-01_132206.jpg
  

8C) QGIS path — WFS‑T (GeoServer/QGIS Server)

POST /geoserver/wfs
Content-Type: text/xml
<wfs:Transaction service="WFS" version="1.1.0">
  <wfs:Insert>
    <feature:truck_events>
      <feature:event_id>6f8c9…</feature:event_id>
      <feature:geom><gml:Point srsName="EPSG:4326"><gml:pos>47.6080 -122.3352</gml:pos></gml:Point></feature:geom>
      <feature:event_type>contam_flag</feature:event_type>
    </feature:truck_events>
  </wfs:Insert>
</wfs:Transaction>
  

8D) Example GeoJSON feature (edge outbox)

{
  "type":"Feature",
  "geometry":{"type":"Point","coordinates":[-122.3352,47.6080]},
  "properties":{"event_id":"6f8c9…","ts_utc":"2025-11-01T13:22:06Z","route_id":"R-12A",
                "event_type":"contam_flag","severity":2,"image_url":"file://.../frame.jpg"}
}
  

8E) Minimal edge config (YAML)

mqtt:
  broker: mqtt://localhost:1883
  topics:
    events: truck/+/events/#
outbox:
  db: /var/lib/ontruck/outbox.sqlite
  batch_size: 100
  retry_backoff_min: 120s
geofence:
  gpkg: /opt/maps/geofences.gpkg
  layers: ["schools","noise_zones"]
sync:
  mode: arcgis   # or "qgis"
  arcgis:
    feature_url: https://services.arcgis.com/<org>/.../FeatureServer/0
    token_url: https://www.arcgis.com/sharing/rest/oauth2/token
    client_id: ABC...  # stored securely
  qgis:
    api_base: https://gis.example.com/api
    media_bucket: s3://ontruck-media/
  

9) Source links (primary docs)