Skip to content

Sense — Contracts

The wire interface between Sense and its clients (mobile, partners) is defined as Protocol Buffers in axion.sense.contracts.

axion.sense.contracts/
├── buf.yaml          # Buf v2 module config
├── buf.gen.yaml      # Codegen targets: Kotlin (Android), Swift (iOS), C# (backend)
└── proto/
    ├── common.proto
    ├── road_data.proto
    ├── driver_location.proto
    ├── tasks.proto
    └── network_scan.proto

All messages live under package axion.sense.contracts.v1 (versioned for forward-compat).


common.proto

Shared types. No services.

Type Fields
GeoLocation double lat, double lon, double altitude, float accuracy, float speed
TrackPoint int64 timestamp_ms, GeoLocation location, sensor data
FrameImageType (enum) JPEG, PNG
CameraSide (enum) FRONT, BACK, LEFT, RIGHT

road_data.proto

The core mobile → API surface. Implemented by RoadDataServiceImpl in Sense API.

service RoadDataService {
  rpc CreateTrack(CreateTrackRequest)                returns (CreateTrackResponse);
  rpc UploadFrameMetadataBatch(UploadFrameMetadataBatchRequest)
                                                     returns (UploadFrameMetadataBatchResponse);
  rpc CommitFrameBatch(CommitFrameBatchRequest)      returns (CommitFrameBatchResponse);
  rpc ConfirmTrack(ConfirmTrackRequest)              returns (ConfirmTrackResponse);
  rpc UploadTrackLogs(UploadTrackLogsRequest)        returns (UploadTrackLogsResponse);
}
RPC Purpose Side effects
CreateTrack Initialize a track. Client sends route polyline + device info; server returns the track_id. Inserts into Postgres track_logs.
UploadFrameMetadataBatch Reserve N frames, get N presigned S3 URLs for direct upload. Issues presigned URLs only — no DB writes yet.
CommitFrameBatch Once frames are uploaded, send the full per-frame metadata (location + sensors). Inserts into Postgres frame_batches with status committed; publishes axion.sense.track.metadata to Kafka.
ConfirmTrack Mobile reports per-frame status; server triggers the ML pipeline and map-matching. Triggers Worker → ML pipeline flow; also enqueues map-matching via Valhalla.
UploadTrackLogs Optional debug log file URLs from the device. Stores keys in Postgres.

The state machine, in two-step form:

stateDiagram-v2
  [*] --> Created : CreateTrack
  Created --> FramesReserved : UploadFrameMetadataBatch
  FramesReserved --> FramesCommitted : CommitFrameBatch
  FramesCommitted --> Confirmed : ConfirmTrack
  Confirmed --> [*]

See the full Frame upload + ML flow for the network-level picture.


driver_location.proto

service DriverLocationService {
  rpc UpdateDriverPosition(UpdateDriverPositionRequest) returns (UpdateDriverPositionResponse);
}

Push the driver's position at intervals or on change. The request carries the active detour task ID (if any) so the server can update task progress.


tasks.proto

service DetourTaskService {
  rpc GetDetourTasks(GetDetourTasksRequest)         returns (GetDetourTasksResponse);
  rpc UpdateDetourTaskStatus(UpdateDetourTaskStatusRequest)
                                                     returns (UpdateDetourTaskStatusResponse);
  rpc GetPriorityLayers(GetPriorityLayersRequest)   returns (GetPriorityLayersResponse);
}

GetDetourTasks is delta-synced (last_sync_time) so the mobile app pulls only what changed.

DetourTask: - id, title, geometry_wkt, assigned_driver_id, percent_completed, deadline - status: AVAILABLEIN_PROGRESSCOMPLETEDVERIFIED / REJECTED / CANCELED - priority: NORMAL / HIGH / CRITICAL

stateDiagram-v2
  [*] --> AVAILABLE
  AVAILABLE --> IN_PROGRESS : claim
  IN_PROGRESS --> COMPLETED : finish
  IN_PROGRESS --> AVAILABLE : release
  COMPLETED --> VERIFIED : approve
  COMPLETED --> REJECTED : reject
  IN_PROGRESS --> CANCELED : cancel
  AVAILABLE --> CANCELED : cancel
  VERIFIED --> [*]
  REJECTED --> [*]
  CANCELED --> [*]

network_scan.proto

Bulk uploads of WiFi and cellular scans for indoor / signal-quality analysis.

service NetworkScanService {
  rpc UploadWifiScans(UploadWifiScansRequest) returns (UploadWifiScansResponse);
  rpc UploadCellScans(UploadCellScansRequest) returns (UploadCellScansResponse);
}

Captured fields:

  • WiFi: BSSID, SSID, RSSI, frequency, standard (802.11a/b/g/n/ac/ax/be), security (Open / WEP / WPA* / EAP), channel width, connected flag.
  • Cell: radio type (GSM / CDMA / WCDMA / LTE / NR), MCC/MNC, LAC, CID, RSSI/RSRP/RSRQ/SINR, timing advance.

Code generation

buf.gen.yaml produces:

  • Kotlin + gRPC Kotlin stubs → gen/kotlin/ (Android)
  • Swift + gRPC Swift stubs → gen/swift/ (iOS)
  • C# + gRPC C# stubs → consumed by axion.sense.backend (Sense API references the proto repo as a submodule)

Regenerate with buf generate from the contracts repo root.

Versioning

The package is axion.sense.contracts.v1. New additions are made backwards-compat by adding fields with new tag numbers. Breaking changes get a new v2 package. The mobile app pins a contract revision.