{
  "feature": "stop-detection",
  "version": "1.0.0",
  "description": "Detect and record periods when a vehicle is stationary, capturing stop location, start time, end time, and duration, to support idle time analysis, delivery dwell time reporting, and route compliance.",
  "category": "workflow",
  "tags": [
    "gps",
    "tracking",
    "stop",
    "idle",
    "dwell",
    "fleet",
    "report"
  ],
  "actors": [
    {
      "id": "pipeline",
      "name": "Position Processing Pipeline",
      "type": "system",
      "description": "Identifies stationary periods from consecutive positions using speed and time thresholds"
    },
    {
      "id": "fleet_user",
      "name": "Fleet User",
      "type": "human",
      "description": "Reviews stop reports to analyse idle time, unscheduled stops, and delivery durations"
    }
  ],
  "fields": [
    {
      "name": "device_id",
      "type": "hidden",
      "required": true,
      "label": "Device being monitored"
    },
    {
      "name": "stop_latitude",
      "type": "number",
      "required": false,
      "label": "Latitude of the stop location"
    },
    {
      "name": "stop_longitude",
      "type": "number",
      "required": false,
      "label": "Longitude of the stop location"
    },
    {
      "name": "stop_start_time",
      "type": "datetime",
      "required": false,
      "label": "Timestamp when movement ceased and the stop began"
    },
    {
      "name": "stop_end_time",
      "type": "datetime",
      "required": false,
      "label": "Timestamp when movement resumed and the stop ended"
    },
    {
      "name": "stop_duration_seconds",
      "type": "number",
      "required": false,
      "label": "Total duration of the stop in seconds"
    },
    {
      "name": "stop_gap_seconds",
      "type": "number",
      "required": false,
      "label": "Minimum seconds of stillness required before a period is classified as a stop"
    }
  ],
  "rules": {
    "rule_1": "A stop is detected when the device remains below the motion speed threshold for at least stop_gap_seconds",
    "rule_2": "Short stationary periods below stop_gap_seconds (e.g., red lights, traffic) are not classified as stops",
    "rule_3": "A stop ends and a new trip may begin when the device's speed exceeds the motion threshold again",
    "rule_4": "Stop location is the coordinates at which movement first ceased; minor GPS drift during a stop is ignored",
    "rule_5": "Stop records include the reverse-geocoded address when available",
    "rule_6": "Stops that overlap with geofence zones are annotated with the zone name for context",
    "rule_7": "Engine hours and fuel data at stop boundaries are recorded to support idle fuel consumption analysis"
  },
  "outcomes": {
    "stop_detected": {
      "priority": 10,
      "given": [
        "device speed has been below the motion threshold for >= stop_gap_seconds",
        "device was previously in a moving state"
      ],
      "then": [
        {
          "action": "create_record",
          "target": "event",
          "description": "Stop detected event recorded with type = device_stopped, stop start time and coordinates",
          "type": "event"
        },
        {
          "action": "emit_event",
          "event": "stop.detected",
          "payload": [
            "device_id",
            "stop_latitude",
            "stop_longitude",
            "stop_start_time",
            "position_id"
          ]
        }
      ],
      "result": "Stop record started; location, time, and sensor values at stop onset captured"
    },
    "stop_ended": {
      "priority": 10,
      "given": [
        "device resumes movement after a recorded stop",
        "device speed exceeds motion threshold"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "stop_end_time",
          "value": "now"
        },
        {
          "action": "emit_event",
          "event": "stop.ended",
          "payload": [
            "device_id",
            "stop_start_time",
            "stop_end_time",
            "stop_duration_seconds",
            "stop_latitude",
            "stop_longitude"
          ]
        }
      ],
      "result": "Stop record closed with end time and duration; available for stop reports"
    },
    "brief_halt_ignored": {
      "priority": 5,
      "given": [
        "device speed dropped to zero but resumed movement within stop_gap_seconds"
      ],
      "then": [],
      "result": "Short halt ignored; no stop record created (traffic light, junction, etc.)"
    }
  },
  "errors": [
    {
      "code": "STOP_DEVICE_NOT_FOUND",
      "message": "The device referenced does not exist",
      "status": 404
    }
  ],
  "events": [
    {
      "name": "stop.detected",
      "description": "Vehicle has come to a stop for longer than the minimum stop threshold",
      "payload": [
        "device_id",
        "stop_latitude",
        "stop_longitude",
        "stop_start_time",
        "geofence_ids"
      ]
    },
    {
      "name": "stop.ended",
      "description": "Vehicle has resumed movement after a recorded stop",
      "payload": [
        "device_id",
        "stop_start_time",
        "stop_end_time",
        "stop_duration_seconds"
      ]
    }
  ],
  "related": [
    {
      "feature": "trip-detection",
      "type": "required",
      "reason": "Stops are the inverse of trips; both use the same motion state machine"
    },
    {
      "feature": "gps-position-ingestion",
      "type": "required",
      "reason": "Position speed values drive stop detection"
    },
    {
      "feature": "geofence-management",
      "type": "recommended",
      "reason": "Stops inside geofences are annotated with zone context"
    },
    {
      "feature": "fleet-scheduled-reports",
      "type": "recommended",
      "reason": "Stop records feed into scheduled stop reports"
    }
  ],
  "agi": {
    "goals": [
      {
        "id": "reliable_stop_detection",
        "description": "Detect and record periods when a vehicle is stationary, capturing stop location, start time, end time, and duration, to support idle time analysis, delivery dwell time reporting, and route compliance.",
        "success_metrics": [
          {
            "metric": "processing_time",
            "target": "< 5s",
            "measurement": "Time from request to completion"
          },
          {
            "metric": "success_rate",
            "target": ">= 99%",
            "measurement": "Successful operations divided by total attempts"
          }
        ],
        "constraints": [
          {
            "type": "performance",
            "description": "Must not block dependent workflows",
            "negotiable": true
          }
        ]
      }
    ],
    "autonomy": {
      "level": "semi_autonomous",
      "human_checkpoints": [
        "before making irreversible changes"
      ],
      "escalation_triggers": [
        "error_rate > 5"
      ]
    },
    "safety": {
      "action_permissions": [
        {
          "action": "stop_detected",
          "permission": "autonomous"
        },
        {
          "action": "stop_ended",
          "permission": "autonomous"
        },
        {
          "action": "brief_halt_ignored",
          "permission": "autonomous"
        }
      ]
    },
    "tradeoffs": [
      {
        "prefer": "reliability",
        "over": "speed",
        "reason": "workflow steps must complete correctly before proceeding"
      }
    ],
    "coordination": {
      "protocol": "orchestrated",
      "consumes": [
        {
          "capability": "trip_detection",
          "from": "trip-detection",
          "fallback": "degrade"
        },
        {
          "capability": "gps_position_ingestion",
          "from": "gps-position-ingestion",
          "fallback": "degrade"
        }
      ]
    }
  },
  "extensions": {
    "source": {
      "repo": "https://github.com/traccar/traccar",
      "project": "Traccar GPS Tracking Server",
      "tech_stack": "Java 17, Netty",
      "files_traced": 6,
      "entry_points": [
        "src/main/java/org/traccar/handler/events/MotionEventHandler.java",
        "src/main/java/org/traccar/session/state/MotionProcessor.java",
        "src/main/java/org/traccar/reports/StopsReportProvider.java"
      ]
    }
  }
}