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