Files
chicken-counting-sukawarna-det/API.md
T

11 KiB
Raw Blame History

Chicken Counter API

Base URL: http://<jetson-ip>:8080

System Status & Live Monitoring

GET /api/status

Returns real-time pipeline activity status, active streaming cameras, latest processed date, and all-time total counts.

{
  "status": "running",
  "is_counting_active": true,
  "active_cameras": ["CC1", "CC2", "CC3", "CC4"],
  "latest_counted_date": "2026-06-18",
  "total_chickens_all_time": 146418,
  "cycle_start_date": "2026-05-22",
  "timestamp": "2026-08-14T08:30:00.000000+00:00"
}

GET /

Returns the dashboard HTML page.

GET /api/cameras

List cameras currently writing to /dev/shm.

{"cameras": ["CC1", "CC2", "CC3"]}

GET /shm/<camera_id>/stats.json

Live stats for the active pipeline.

{
  "frame_index": 5120,
  "inside_box_count": 42,
  "total_entered_count": 1858,
  "track_count": 99,
  "backward_active": false,
  "smoothed_speed": 4.3,
  "count_events": 0,
  "run_date": "2026-06-10"
}

GET /shm/<camera_id>/frame.jpg

Live JPEG frame from the active pipeline.


Database

All endpoints require the dashboard to be started with --db <path>. If no DB exists, endpoints return [] or {}.

GET /api/config/cycle_start_date

Returns or updates the active Day 0 (cycle_start_date).

# Query active Day 0
GET /api/config/cycle_start_date
→ {"cycle_start_date": "2026-05-22"}

# Override Day 0 dynamically via query param or POST payload
GET /api/config/cycle_start_date?set=2026-05-22
POST /api/config/cycle_start_date  {"cycle_start_date": "2026-05-22"}
→ {"status": "ok", "cycle_start_date": "2026-05-22"}

GET /api/db/summary

Overall totals across all dates and locations.

{
  "days": 12,
  "locations": 2,
  "total_runs": 48,
  "total_chickens": 125000,
  "total_hours": 8.5
}

GET /api/db/history

Per-date summary, newest first (max 50 rows).

[
  {
    "date": "2026-06-10",
    "location": "kandang-atas",
    "cams": 4,
    "total": 5570,
    "minutes": 40.2
  }
]

GET /api/db/date/<date>

Detail for a specific date. Format: YYYY-MM-DD.

{
  "date": "2026-06-10",
  "total": {"total": 5570, "minutes": 40.2},
  "cameras": [
    {
      "camera_id": "CC1",
      "total_entered": 1500,
      "frames_processed": 24800,
      "elapsed_seconds": 600.5,
      "stopped_reason": "backward",
      "source_video": "kandang_1_camera_1_2026-06-10_120056.mp4",
      "location": "kandang-atas"
    }
  ]
}

GET /api/db/camera/<camera_id>

History for a specific camera across all dates (max 50 rows).

[
  {
    "date": "2026-06-10",
    "location": "kandang-atas",
    "total_entered": 1500,
    "frames_processed": 24800,
    "elapsed_seconds": 600.5,
    "stopped_reason": "backward"
  }
]

GET /api/db/location/<location>

Summary and history for a specific location.

{
  "location": "kandang-atas",
  "summary": {"days": 5, "total": 25000, "hours": 3.2},
  "history": [
    {
      "date": "2026-06-10",
      "cameras": "CC1, CC2, CC3, CC4",
      "total": 5570,
      "minutes": 40.2
    }
  ]
}

Database Schema

CREATE TABLE batch_runs (
    id               INTEGER PRIMARY KEY AUTOINCREMENT,
    date             TEXT    NOT NULL,
    location         TEXT    NOT NULL,
    camera_id        TEXT    NOT NULL,
    total_entered    INTEGER NOT NULL DEFAULT 0,
    frames_processed INTEGER NOT NULL DEFAULT 0,
    elapsed_seconds  REAL    NOT NULL DEFAULT 0.0,
    stopped_reason   TEXT    NOT NULL DEFAULT '',
    source_video     TEXT    NOT NULL DEFAULT '',
    generated_at     TEXT    NOT NULL DEFAULT '',
    UNIQUE(date, location, camera_id)
);

Data is inserted automatically by the batch runner when location and db_path are configured in the batch YAML, or manually via:

python3 store_results.py output/counts_2026-06-10.json --location kandang-atas --db chicken_counts.db

Mortality Detection

Mortality endpoints require the dashboard to be started with --mortality-dir <path>. The path must contain a mortality_report.json file generated by ./test_run_mortality.sh. Multiple directories can be registered with repeated --mortality-dir flags.

If multiple images are captured in a single day (e.g. morning and afternoon scans), the pipeline processes all images in the input directory, generates marked output JPEGs (output_<name>.jpg), and aggregates the daily total carcass count into total_mortality_count.

GET /api/mortality/coops

Returns a summary of all detected coops with their covered floors and mortality figures:

[
  {
    "coop": "K1",
    "covered_floors": ["K1-L1", "K1-L2", "K1-L3"],
    "total_carcasses": 12,
    "total_scans": 3,
    "latest_date": "2026-06-18",
    "latest_count": 4
  },
  {
    "coop": "K2",
    "covered_floors": ["K2-L1", "K2-L2", "K2-L3"],
    "total_carcasses": 8,
    "total_scans": 2,
    "latest_date": "2026-06-18",
    "latest_count": 8
  }
]

GET /api/mortality/coop/<coop_id>

Returns all mortality reports recorded for a specific coop (e.g. GET /api/mortality/coop/K1).

GET /api/mortality/latest

Returns the most recent mortality_report.json across all coop directories, enriched with coop and covered_floors:

{
  "date": "2026-06-18",
  "coop": "K1",
  "location": "K1",
  "covered_floors": ["K1-L1", "K1-L2", "K1-L3"],
  "total_mortality_count": 19,
  "total_images": 1,
  "_dir": "/path/to/VIDEOS/cycle7/K1/mortality",
  "results": [...]
}

GET /api/mortality/history

Returns all mortality_report.json files from all registered coop directories, sorted newest first. Each report contains coop, covered_floors, total_mortality_count, and total_images.

GET /api/mortality/date/<YYYY-MM-DD>

Returns all mortality scans and total carcass counts recorded on a specific date:

{
  "date": "2026-06-18",
  "total_mortality_count": 35,
  "total_images": 2,
  "reports": [...],
  "results": [...]
}

POST /api/mortality/capture

Snaps a high-resolution still frame directly from the dedicated stationary inspection camera for a specific coop, runs YOLO carcass detection, saves the image into VIDEOS/cycle7/<coop>/mortality/<date>/capture_XX_<timestamp>.jpg, and returns the detection count.

Content-Type: application/json or multipart/form-data or Query Parameters

Request Parameters:

  • coop (string, required): Coop identifier (e.g. K1, K2, kandang-atas).
  • date (string, optional): Date in YYYY-MM-DD format (defaults to today).
  • source (string, optional): Override camera RTSP stream / device URL. If omitted, uses the configured camera in configs/mortality_config.yaml.
  • conf (float, optional): Confidence threshold override.

Response (200 OK):

{
  "status": "success",
  "message": "Captured photo #2 from K1 camera (12 carcasses)",
  "coop": "K1",
  "date": "2026-08-20",
  "camera_source": "rtsp://admin:admin@192.168.1.101:554/live",
  "captured_file": "capture_02_20260820_103000.jpg",
  "batch_count": 12,
  "total_images": 2,
  "total_mortality_count": 30,
  "results": [...]
}

GET /api/mortality/camera/preview?coop=<coop_id>

Returns a live JPEG snapshot frame from that coop's stationary camera so workers can verify chicken positioning before capturing.

GET /api/mortality/camera/preview?coop=K1
→ Content-Type: image/jpeg

GET /api/mortality/cameras

Returns the map of all registered stationary cameras per coop.

{
  "cameras": {
    "K1": "rtsp://admin:admin@192.168.1.101:554/live",
    "K2": "rtsp://admin:admin@192.168.1.102:554/live",
    "K3": "rtsp://admin:admin@192.168.1.103:554/live",
    "K4": "rtsp://admin:admin@192.168.1.104:554/live",
    "K5": "rtsp://admin:admin@192.168.1.105:554/live"
  }
}

POST /api/mortality/upload

Uploads one or more mortality photos from disk for a specific coop, runs YOLO carcass detection immediately, saves results into VIDEOS/cycle7/<coop>/mortality/<date>/, and returns detection results.

Content-Type: multipart/form-data

Form Fields:

  • coop (string, required): Coop identifier (e.g. K1, K2, kandang-atas).
  • date (string, optional): Date in YYYY-MM-DD format (defaults to current date).
  • conf (float, optional): Confidence threshold override (e.g. 0.7).
  • two_pass (boolean, optional): Set true for 2-pass refinement.
  • images (file/binary, repeatable): 1 or more image files (.jpg, .jpeg, .png).

Response (200 OK):

{
  "status": "success",
  "message": "Processed 2 image(s) for K1",
  "coop": "K1",
  "date": "2026-08-20",
  "total_images": 2,
  "total_mortality_count": 29,
  "results": [
    {
      "input_image": "batch_1.jpg",
      "output_image": "output_batch_1.jpg",
      "count": 19,
      "output_path": "/path/to/VIDEOS/cycle7/K1/mortality/2026-08-20/output_batch_1.jpg",
      "detections": [...]
    }
  ]
}

POST /api/mortality/scan

Triggers immediate re-scanning of an existing coop directory:

Request Body (application/json):

{
  "coop": "K1",
  "date": "2026-08-20"
}

GET /api/mortality/image/<filename>

Serves an annotated output JPEG by filename securely. Only files beginning with output_ are accessible for security.

GET /api/mortality/image/output_scan_01.jpg
→ Content-Type: image/jpeg

Starting the Dashboard

Use the portable launcher script which auto-discovers the mortality directory:

./start_dashboard.sh

Optional environment variables:

Variable Default Description
PORT 8080 Port to listen on
DB_PATH db/chicken_counts.db Path to SQLite database
MORTALITY_DIRS auto-detected Comma-separated mortality dirs

Or start manually with full control:

PYTHONPATH=src venv/bin/python dashboard.py \
  --port 8080 \
  --db db/chicken_counts.db \
  --mortality-dir /path/to/mortality \
  --mortality-dir /path/to/another/mortality

Outbound System Notifications & Webhooks

When integrating with external management systems or cloud backends, you can query status or send automated event notifications (e.g. STARTED, COMPLETED, MORTALITY_DETECTED).

1. Polling Pipeline State

External systems can poll GET http://<jetson-ip>:8080/api/status every 5–10 seconds to detect if counting or mortality runs are currently in progress or finished.

2. Sending Outbound Webhook from Shell / Batch Scripts

To notify an external endpoint (e.g. https://your-server.com/api/notify) upon run lifecycle events:

# Example: Notify external server when counting starts
curl -X POST https://your-server.com/api/notify \
  -H "Content-Type: application/json" \
  -d '{"event": "COUNTING_STARTED", "date": "2026-06-18", "device": "jetson-sukawarna"}'

# Example: Notify external server when counting completes with JSON payload
curl -X POST https://your-server.com/api/notify \
  -H "Content-Type: application/json" \
  -d @/home/asus/.Codes/VIDEOS/cycle7/kandang-atas/2026-06-18/output/counts_2026-06-18.json

# Example: Notify external server when mortality scan finishes
curl -X POST https://your-server.com/api/notify \
  -H "Content-Type: application/json" \
  -d @/home/asus/.Codes/VIDEOS/cycle7/kandang-atas/mortality/mortality_report.json