Skip to content

Image Processor API

The Image Processor API handles traffic image processing with ANPR (Automatic Number Plate Recognition) integration, violation detection, API health monitoring, and pending events queue management.

Overview

ProcedureTypeAuthDescription
traffic.imageProcessor.processImageMutationNo*Process image with ANPR and route events
traffic.imageProcessor.getAPIHealthQueryNoGet ANPR API health status
traffic.imageProcessor.resetAPIHealthMutationYesReset API health and clear cooloff
traffic.imageProcessor.getPendingStatsQueryNoGet pending events queue statistics
traffic.imageProcessor.getPendingEventsQueryYesGet paginated pending events
traffic.imageProcessor.processPendingEventsMutationYesProcess pending events manually
traffic.imageProcessor.retryFailedEventsMutationYesRetry all failed events
traffic.imageProcessor.cancelPendingEventsMutationYesCancel specific pending events
traffic.imageProcessor.cleanupOldEventsMutationYesDelete old processed/failed events
traffic.imageProcessor.getSpeedThresholdQueryNoGet speed threshold for location
traffic.imageProcessor.setLocationSpeedThresholdMutationYesSet location speed threshold
traffic.imageProcessor.getSystemSpeedThresholdQueryNoGet system default threshold
traffic.imageProcessor.setSystemSpeedThresholdMutationYesSet system default threshold
traffic.imageProcessor.getViolationStatsQueryYesGet violation statistics

*Requires sensor API key

Event Routing Logic

The image processor routes events to different tables based on detection results:

Image Processing Flow:

  ├─ API Unavailable? → Queue as PendingEvent

  ├─ No vehicle detected → IGNORED (not saved)

  ├─ Speed > threshold → Creates:
  │   ├─ SpeedEvent (speed violation record)
  │   └─ Event (traffic event with violations)

  └─ Speed <= threshold → Creates:
      └─ Event only (with ANPR violations if any)

Violation Types

typescript
const VIOLATION_TYPES = {
  SEATBELT: "SEATBELT",       // Person without seatbelt
  HELMET: "HELMET",           // Rider without helmet
  PHONE_USAGE: "PHONE_USAGE", // Single-hand driving
  TRIPLE_RIDE: "TRIPLE_RIDE", // >2 persons on two-wheeler
  TAILLIGHT: "TAILLIGHT",     // Taillight off
} as const;

Vehicle Classes

typescript
const VEHICLE_CLASSES = {
  CAR: "CAR",
  TWO_WHEELER: "TWO_WHEELER",
  TRUCK: "TRUCK",
  LCV: "LCV",
  BUS: "BUS",
  AUTO: "AUTO",
} as const;

API Health Status

typescript
const API_STATUS = {
  UP: "UP",           // API is operational
  DOWN: "DOWN",       // API is down (incident created)
  DEGRADED: "DEGRADED", // API experiencing issues
} as const;

Procedures

traffic.imageProcessor.processImage

Main entry point for processing traffic images with ANPR.

Type: Mutation Auth Required: Sensor API Key (via sensorId)

Input

typescript
{
  // Image source (one required)
  imageBase64?: string;
  imageUrl?: string;

  // Speed data from radar (optional)
  speedKmh?: number;

  // Location/Sensor info
  sensorId: string;
  locationId?: string;
  locationName?: string;

  // Radar-specific fields (optional)
  targetId?: number;
  eventType?: number;         // Default: 1 (LINE_CROSSING)
  laneNumber?: number;
  linePosition?: number;
  crossingDirection?: number;
  lateralPosition?: number;
  distance?: number;
  captureTimestamp?: number;

  // ANPR options
  anprOptions?: {
    zone_name?: string;
    enable_taillight?: boolean;
    enable_lp_color?: boolean;
  };

  // Skip ANPR processing
  skipANPR?: boolean;
}

Response

typescript
{
  success: boolean;
  routing: "SPEED_EVENT" | "TRAFFIC_EVENT" | "IGNORED";
  eventId: string | null;
  speedEventId: string | null;
  anpr: ProcessedANPRResult | null;
  violations: DetectedViolation[];
  message: string;
  // Queue info (when API unavailable)
  queued: boolean;
  pendingEventId: string | null;
  queuePosition: number | null;
  apiStatus: "UP" | "DOWN" | "DEGRADED" | null;
}

Example

bash
curl -X POST "https://api.itms.solutions/trpc/traffic.imageProcessor.processImage" \
  -H "Content-Type: application/json" \
  -d '{
    "json": {
      "sensorId": "sensor-123",
      "imageUrl": "https://storage.example.com/capture.jpg",
      "speedKmh": 85,
      "locationName": "Main Street Intersection",
      "anprOptions": {
        "enable_taillight": true,
        "enable_lp_color": true
      }
    }
  }'

Response Example (Speed Violation)

json
{
  "result": {
    "data": {
      "json": {
        "success": true,
        "routing": "SPEED_EVENT",
        "eventId": "evt-456",
        "speedEventId": "spd-789",
        "anpr": {
          "success": true,
          "licensePlateNumber": "KZ 123 ABC",
          "plateConfidence": 0.95,
          "vehicleType": "CAR",
          "vehicleConfidence": 0.92,
          "vehiclesDetected": 1,
          "hasViolations": false,
          "violations": []
        },
        "violations": [],
        "message": "Speed violation: 85 km/h (limit: 35 km/h). Created SpeedEvent and TrafficEvent.",
        "queued": false,
        "pendingEventId": null,
        "queuePosition": null,
        "apiStatus": "UP"
      }
    }
  }
}

Response Example (API Unavailable - Queued)

json
{
  "result": {
    "data": {
      "json": {
        "success": true,
        "routing": "IGNORED",
        "eventId": null,
        "speedEventId": null,
        "anpr": null,
        "violations": [],
        "message": "ANPR API unavailable. Event queued for later processing. API in cooloff period. 245s remaining.",
        "queued": true,
        "pendingEventId": "pnd-123",
        "queuePosition": 15,
        "apiStatus": "DOWN"
      }
    }
  }
}

traffic.imageProcessor.getAPIHealth

Get health status of external APIs (ANPR).

Type: Query Auth Required: No

Input

typescript
{
  apiName?: string;  // Optional: filter by API name
}

Response

typescript
{
  apis: Array<{
    id: string;
    apiName: string;
    status: "UP" | "DOWN" | "DEGRADED";
    lastSuccessAt: string | null;
    lastFailureAt: string | null;
    consecutiveFailures: number;
    consecutiveSuccesses: number;
    cooloffUntil: string | null;
    cooloffRemaining: number | null;  // seconds
    lastError: string | null;
    totalCalls: number;
    totalSuccesses: number;
    totalFailures: number;
    avgResponseTimeMs: number | null;
    available: boolean;
    reason: string | null;
  }>;
}

Example

bash
curl "https://api.itms.solutions/trpc/traffic.imageProcessor.getAPIHealth" \
  -H "Content-Type: application/json"

traffic.imageProcessor.resetAPIHealth

Reset API health status and clear cooloff period.

Type: Mutation Auth Required: Yes

Input

typescript
{
  apiName: string;  // e.g., "ANPR_API"
}

Response

typescript
{
  success: boolean;
  message: string;
}

traffic.imageProcessor.getPendingStats

Get statistics for the pending events queue.

Type: Query Auth Required: No

Input

typescript
{
  apiName?: string;  // Optional: filter by API
}

Response

typescript
{
  pending: number;
  processing: number;
  processed: number;
  failed: number;
  total: number;
  oldestPending: string | null;  // ISO timestamp
}

Example

bash
curl "https://api.itms.solutions/trpc/traffic.imageProcessor.getPendingStats" \
  -H "Content-Type: application/json"

traffic.imageProcessor.processPendingEvents

Manually trigger processing of pending events.

Type: Mutation Auth Required: Yes

Input

typescript
{
  limit?: number;     // Max events to process (1-100, default: 50)
  apiName?: string;   // Filter by API
}

Response

typescript
{
  success: boolean;
  processed: number;
  failed: number;
  remaining: number;
  message: string;
}

Example

bash
curl -X POST "https://api.itms.solutions/trpc/traffic.imageProcessor.processPendingEvents" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "json": {
      "limit": 50
    }
  }'

traffic.imageProcessor.retryFailedEvents

Move all failed events back to pending queue for retry.

Type: Mutation Auth Required: Yes

Input

typescript
{
  apiName?: string;  // Optional: filter by API
}

Response

typescript
{
  success: boolean;
  retriedCount: number;
  message: string;
}

traffic.imageProcessor.getSpeedThreshold

Get the speed threshold for a specific location or sensor.

Type: Query Auth Required: No

Input

typescript
{
  sensorId?: string;
  locationId?: string;
}

Response

typescript
{
  threshold: number;  // km/h
  default: number;    // System default (35 km/h)
}

traffic.imageProcessor.setLocationSpeedThreshold

Set the speed threshold for a specific location.

Type: Mutation Auth Required: Yes

Input

typescript
{
  locationId: string;
  threshold: number;  // 0-300 km/h
}

Response

typescript
{
  success: boolean;
  threshold: number;
}

traffic.imageProcessor.getViolationStats

Get violation statistics with filtering.

Type: Query Auth Required: Yes

Input

typescript
{
  startDate?: string;   // ISO timestamp
  endDate?: string;     // ISO timestamp
  sensorId?: string;
  locationId?: string;
}

Response

typescript
{
  total: number;
  byType: Array<{ violationType: string; count: number }>;
  byVehicle: Array<{ vehicleType: string; count: number }>;
  dailyTrend: Array<{ date: string; count: number }>;
  violationTypes: string[];
}

API Health Circuit Breaker

The system implements a circuit breaker pattern for external API calls:

Configuration

SettingDefaultDescription
Cooloff Duration300s (5 min)Time to wait before retrying
Failure Threshold3Consecutive failures before DOWN
Recovery Threshold2Consecutive successes to recover

State Transitions

UP ─────────────────────────────────────────────────────────────► UP
 │                                                                 ▲
 │ 1-2 failures                                                    │
 ▼                                                                 │
DEGRADED ──────────────────────────────────────────────────────────┤
 │                                                                 │
 │ 3+ failures                           2+ consecutive successes  │
 ▼                                                                 │
DOWN ──────── cooloff period ends ──────► retry ───────────────────┘

Incident Creation

When API status transitions to DOWN:

  1. An Alert is created with severity CRITICAL
  2. Incident ID is stored in APIHealthStatus
  3. When API recovers, incident is automatically resolved

Pending Events Queue

Events are queued when the ANPR API is unavailable:

Event Lifecycle

1. PENDING   → Event created, waiting for retry
2. PROCESSING → Currently being processed
3. PROCESSED  → Successfully processed, result stored
4. FAILED     → Processing failed after max retries

Retry Strategy

  • Exponential Backoff: 1min → 2min → 4min → ... (max 1 hour)
  • Max Retries: 3 (configurable)
  • Priority: Speed violations get higher priority

Cleanup

Use cleanupOldEvents to remove old processed/failed events:

  • Default retention: 7 days
  • Configurable: 1-365 days

Error Codes

CodeDescription
INTERNAL_SERVER_ERRORDatabase not available
BAD_REQUESTMissing required image (base64 or URL)
NOT_FOUNDEvent or resource not found
UNAUTHORIZEDInvalid or missing authentication

SCS Smart City - Traffic, Gateway, Camera, and NVR Platform