api_version: cmvr.edge.ai/v1

runtime:
  thread_workers: 3
  shutdown_timeout_s: 8

endpoints:
  cmvr_es:
    transport: grpc
    # cmvr-es gRPC address. Change this value for each deployed robot.
    target: 192.168.0.102:50052
    tls: false
    timeout_s: 5
    options:
      max_receive_mb: 32

  platform:
    transport: http
    # Violation-alert platform HTTP base URL.
    base_url: http://127.0.0.1:8081
    timeout_s: 3

pipelines:
  detection:
    enabled: true
    nodes:
      camera:
        uses: cmvr.grpc.camera_rgb_stream@1
        with:
          endpoint: cmvr_es
          device_id: wrist_cam
          pixel_format: BGR8
          reconnect: true
          reconnect_initial_s: 0.5
          reconnect_max_s: 10
          # Log stream state immediately on first frame and emit a periodic
          # progress/stall heartbeat without printing every encoded frame.
          stream_log_interval_s: 5

      decoder:
        uses: media.video_decoder.pyav@1

      detector:
        uses: detection.model@1
        with:
          model: construction-ppe-yolov8@1
          # Omitting detect_labels means all registered labels.  This example
          # asks the backend to return only PPE violations used by the rules.
          detect_labels:
            - No-Boots
            - No-Ear-Protection
            - No-Glass
            - No-Glove
            - No-Helmet
            - No-Mask
            - No-Vest
          confidence: 0.50
          max_fps: 10
          # Log the first completed inference immediately, then aggregate one
          # heartbeat every 5 seconds so model activity is visible without
          # printing every frame. Set to 1 for one-second debugging, or omit to disable.
          inference_log_interval_s: 5
          # Keep the decoded threshold frame available to repeat_gate so an
          # annotated alert image can be rendered only when a rule triggers.
          attach_frame: true
          model_options:
            # Model artifact and inference device are deployment configuration,
            # not process environment requirements.
            weights: /home/xtkuang/Projects/cmvr/changan_robot/construction-ppe-yolov8/best.pt
            device: cpu
            imgsz: 640
            iou: 0.70
            half: false
            max_det: 100

      repeat_gate:
        uses: detection.repeat_gate@1
        with:
          # cmvr-es currently omits capture timestamps on successful stream
          # frames, so received time is the deterministic deployment default.
          time_source: received
          alert_image:
            enabled: true
            jpeg_quality: 85
          rules:
            - id: no-boots
              labels: [No-Boots]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-ear-protection
              labels: [No-Ear-Protection]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-glass
              labels: [No-Glass]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-glove
              labels: [No-Glove]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-helmet
              labels: [No-Helmet]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-mask
              labels: [No-Mask]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source
            - id: no-vest
              labels: [No-Vest]
              min_hits: 3
              window_ms: 2000
              cooldown_ms: 30000
              min_confidence: 0.50
              scope: source

      platform:
        uses: platform.http_json_sink@1
        with:
          endpoint: platform
          path: /v1/detection-alerts
          # Platform outages must not stop camera capture or inference. After
          # bounded retries, log a WARNING and drop only this report.
          failure_mode: log_and_drop
          max_attempts: 3
          retry_initial_s: 0.25
          retry_max_s: 2

    edges:
      # Encoded H264/H265 packets must remain contiguous before decode.
      - from: camera.frames
        to: decoder.frames
        qos:
          profile: video_contiguous
          capacity: 8
          overflow: block

      # Once frames are decoded, keeping only the newest frame bounds latency.
      - from: decoder.frames
        to: detector.frames
        qos:
          profile: realtime_latest
          capacity: 1
          overflow: drop_oldest

      - from: detector.detections
        to: repeat_gate.detections
        qos:
          profile: telemetry
          # DetectionResult carries a decoded frame when attach_frame is enabled;
          # keep this queue short so raw image buffers cannot accumulate. Under
          # sustained overload drop_oldest also means dropped results do not count.
          capacity: 2
          overflow: drop_oldest

      - from: repeat_gate.alerts
        to: platform.input
        qos:
          profile: telemetry
          capacity: 64
          overflow: block
