Nodeflux Central
PPE Analytics

API Reference — PPE Analytics

Endpoint REST API untuk membuat, mengelola, dan memantau pipeline PPE Analytics (NFV4-PPE), serta struktur event JSON.

Semua endpoint pada halaman ini menggunakan basis URL dari variabel VISIONAIRE_API_URL (default: http://localhost:4004). Autentikasi mengikuti konfigurasi deployment Visionaire4 Anda. Untuk detail instalasi dan konfigurasi layanan, lihat Instalasi Dependensi.


Manajemen Pipeline

Endpoint untuk membuat, membaca, mengubah, dan menghapus pipeline PPE Analytics pada sebuah stream. Body request untuk POST/PUT dijelaskan lengkap di Konfigurasi.

Buat Pipeline

POST /pipeline/{node_num}/{stream_id}/NFV4-PPE

curl -X POST "http://localhost:4004/pipeline/0/stream_001/NFV4-PPE" \
  -H "Content-Type: application/json" \
  -d '{
    "object_confidence_threshold": 0.53,
    "attributes": {
      "head_protection_confidence_threshold": 0.7,
      "safety_harness_confidence_threshold": 0.7
    },
    "sub_analytics": [
      {
        "name": "counting",
        "is_active": true,
        "areas": [
          { "name": "Site Entrance", "points": [{ "x": 0, "y": 0.5 }, { "x": 1, "y": 0.5 }], "direction": "in", "bidirection": false }
        ]
      },
      { "name": "roi_counting", "is_active": false },
      { "name": "dwelling", "is_active": false },
      { "name": "density", "is_active": false }
    ]
  }'

Response sukses:

{
  "code": 200,
  "message": "pipeline successfully created",
  "node_num": 0,
  "stream_id": "stream_001",
  "analytic_id": "NFV4-PPE"
}

Jika pipeline NFV4-PPE sudah berjalan pada stream_id yang sama, request mengembalikan HTTP 400 dengan pesan analytic_id=NFV4-PPE is already exists in stream=<stream_id> ! — bukan 409. Gunakan PUT untuk mengubah konfigurasi pipeline yang sudah berjalan.

Ubah Konfigurasi Pipeline

PUT /pipeline/{node_num}/{stream_id}/NFV4-PPE

Mengubah parameter pipeline yang sedang berjalan tanpa restart. Body sama seperti POST; kirim hanya field yang ingin diubah beserta struktur sub_analytics yang relevan.

curl -X PUT "http://localhost:4004/pipeline/0/stream_001/NFV4-PPE" \
  -H "Content-Type: application/json" \
  -d '{ "object_confidence_threshold": 0.4 }'

Baca Konfigurasi Pipeline Aktif

GET /pipeline/{node_num}/{stream_id}/NFV4-PPE

Mengembalikan konfigurasi yang sedang berjalan pada instance pipeline tersebut.

curl "http://localhost:4004/pipeline/0/stream_001/NFV4-PPE"

Hapus Pipeline

DELETE /pipeline/{node_num}/{stream_id}/NFV4-PPE

curl -X DELETE "http://localhost:4004/pipeline/0/stream_001/NFV4-PPE"

Parameter Path

ParameterTipeDeskripsi
node_numintegerNomor node tempat pipeline berjalan (0 = master)
stream_idstringID stream yang akan dianalisis

Konfigurasi & Rules

EndpointDeskripsi
GET /config/pipeline/NFV4-PPE/Skema konfigurasi lengkap NFV4-PPE — daftar parameter per sub-analytic beserta nilai default, tipe, dan batas nilainya. Gunakan untuk membangun form konfigurasi secara dinamis.
GET /v2/config/pipeline/NFV4-PPE/Varian v2 dari endpoint di atas.
GET /rules/pipeline/NFV4-PPE/Daftar field pipeline_data yang dapat dipakai sebagai kondisi alert rule (mis. label, area_name, duration, estimation), beserta opsi nilai atribut PPE yang tersedia.

Tidak ada endpoint preset (GET /config/preset/NFV4-PPE/) yang mengembalikan hasil untuk NFV4-PPE — tidak ada preset terdaftar untuk analitik ini di kode saat ini.


Visualisasi (MJPEG)

GET /mjpeg/{node_num}/{stream_id}/NFV4-PPE

Mengembalikan MJPEG stream dengan overlay deteksi dan ROI dari pipeline yang berjalan — berguna untuk memverifikasi posisi garis/polygon dan hasil deteksi secara visual. Endpoint generik GET /mjpeg/{node_num}/{stream_id} (tanpa analytic_id) juga tersedia dan menampilkan overlay dari seluruh pipeline aktif pada stream tersebut.

Parameter Query (Opsional)

ParameterTipeDeskripsiDefault
fpsintegerFrame rate output MJPEG. 0 berarti mengikuti FPS asli pipeline.0
heightintegerTinggi frame output dalam piksel320
jqintegerKualitas JPEG output (1–100)60
# Buka di browser untuk preview langsung
http://localhost:4004/mjpeg/0/stream_001/NFV4-PPE?fps=15&height=480&jq=70

Bentuk path /pipeline/{node_num}/{stream_id}/NFV4-PPE/mjpeg tidak ada. Endpoint MJPEG berdiri sendiri di /mjpeg/..., bukan sub-path dari /pipeline/.... Endpoint /visual/... juga ada di Visionaire4, tetapi mengembalikan halaman viewer HTML, bukan gambar/stream — gunakan /mjpeg/... jika Anda butuh output gambar untuk diintegrasikan.


Event Streaming (WebSocket)

Visionaire4 mengirim setiap event hasil deteksi/klasifikasi melalui WebSocket. Untuk berlangganan event dari pipeline PPE Analytics pada stream tertentu, buka koneksi ke:

ws://<host>:4004/event_channel/{node_num}/{stream_id}/NFV4-PPE

Setelah koneksi terbuka, server langsung mendorong (push) setiap event ke client tanpa handshake atau pesan subscribe. Tutup koneksi untuk berhenti menerima event.

Parameter Path

ParameterTipeDeskripsi
node_numintegerNomor node tempat stream berjalan (0 = master)
stream_idstringID stream yang akan dipantau

Query Parameter (Opsional)

ParameterTipeDeskripsi
logicstringFilter event berdasarkan nama sub-analytic (counting, roi_counting, dwelling, density) yang aktif pada pipeline. Tanpa parameter ini, semua event dari NFV4-PPE dikirim.

Contoh Koneksi

const ws = new WebSocket(
  'ws://localhost:4004/event_channel/0/<stream_id>/NFV4-PPE'
);

ws.onmessage = (msg) => {
  const event = JSON.parse(msg.data);
  console.log(event.primary_text, event.pipeline_data);
};

ws.onerror = (err) => console.error('WebSocket error', err);
ws.onclose = () => console.log('Disconnected');
import asyncio
import json
import websockets

async def listen():
    url = "ws://localhost:4004/event_channel/0/<stream_id>/NFV4-PPE"
    async with websockets.connect(url) as ws:
        async for msg in ws:
            event = json.loads(msg)
            print(event["primary_text"], event["pipeline_data"])

asyncio.run(listen())

Endpoint Channel Lainnya

EndpointCakupan
WS /event_channel/Semua event dari seluruh node
WS /event_channel/{node_num}/Semua event dari satu node
WS /event_channel/{node_num}/{stream_id}Semua event dari satu stream (semua analitik)

Struktur Event

Setiap event memakai envelope standar Visionaire yang sama di seluruh modul analitik; bagian yang spesifik PPE Analytics ada di pipeline_data, dengan bentuk yang berbeda tergantung sub-analytic mana yang menghasilkannya (logic).

{
  "timestamp": 1705314600,
  "node_num": 0,
  "stream_id": "stream_001",
  "stream_name": "Site Entrance Cam",
  "stream_address": "rtsp://10.7.2.50:554/stream",
  "stream_longitude": 106.823649,
  "stream_latitude": -6.261376,
  "analytic_id": "NFV4-PPE",
  "primary_text": "person",
  "secondary_text": "in",
  "pipeline_data": {
    "confidence": 0.86,
    "label": "person",
    "area_name": "Site Entrance",
    "direction": "in",
    "tracker_id": 5,
    "group_id": 0,
    "logic": "counting",
    "attributes": {
      "personal": { "label": "person", "confidence": 0.86 },
      "safety_glasses": { "label": "No", "confidence": 0.91 },
      "face_shield": { "label": "No", "confidence": 0.88 },
      "gloves": { "label": "Yes", "confidence": 0.77 },
      "safety_harness": { "label": "No", "confidence": 0.85 },
      "head_protection": { "label": "Hard helmet", "confidence": 0.92 },
      "helmet_color": { "label": "Yellow", "confidence": 0.81 },
      "face_mask": { "label": "None", "confidence": 0.74 },
      "protective_clothing": { "label": "Safety vest", "confidence": 0.88 },
      "protective_clothing_color": { "label": "Orange", "confidence": 0.79 },
      "footwear_type": { "label": "Safety boots", "confidence": 0.67 },
      "work_context": { "label": "Construction", "confidence": 0.61 }
    },
    "event_id": "1705314600-3a1f9d4c"
  },
  "image_jpeg": "<base64 JPEG>"
}

Field Envelope

FieldTipeDeskripsi
timestampintWaktu event dalam epoch detik (UTC).
node_numintNomor node tempat pipeline berjalan.
stream_idstringIdentifier stream sumber.
stream_namestringNama stream.
stream_addressstringURL sumber video stream.
stream_longitude, stream_latitudefloatPosisi kamera.
analytic_idstringSelalu NFV4-PPE.
primary_textstringLabel objek ("person") untuk Counting/ROI Counting/Dwelling; nama area untuk Density.
secondary_textstringArah ("in"/"out") untuk Counting/ROI Counting; durasi untuk Dwelling; jumlah orang untuk Density.
pipeline_dataobjectDetail hasil sub-analytic — bentuknya berbeda per logic, lihat tabel berikutnya.
image_jpegstring (base64)Crop JPEG dari objek/area yang menghasilkan event.

Envelope tidak memiliki field event_id di level atas maupun timestamp_ms — keduanya sering disangka ada karena pola di sistem lain. event_id hanya ada di dalam pipeline_data, berformat <timestamp>-<hash8>.

Field pipeline_data

FieldTipeTersedia pada logic
confidencefloatcounting, roi_counting, dwelling
labelstringcounting, roi_counting, dwelling — selalu "person"
area_namestringcounting, roi_counting, dwelling
directionstringcounting, roi_counting — "in" / "out"
tracker_idintcounting, roi_counting, dwelling
group_idintcounting, roi_counting, dwelling — terisi bila enable_group_tracking: true
time_inint (epoch ms)dwelling
time_outint (epoch ms) atau nulldwelling — null bila objek belum keluar ROI saat event dikirim
time_alertint (epoch ms) atau nulldwelling — terisi bila dwelling_treshold_alert_sec terlampaui
durationfloat (detik)dwelling
intervalint (detik)density
areastringdensity — nama polygon
estimationintdensity — jumlah orang di dalam/luar polygon sesuai inside
detectedarraydensity — daftar objek dengan tracker_id, group_id, bbox (top/left/width/height), label, confidence, dan attributes (bila dump_attributes: true)
logicstringsemua — "counting", "roi_counting", "dwelling", atau "density"
attributesobjectcounting, roi_counting, dwelling — lihat di bawah
event_idstringsemua — format <timestamp>-<hash8>

Objek attributes

Objek attributes pada event Counting/ROI Counting/Dwelling (dan pada setiap item detected di event Density bila dump_attributes: true) selalu berisi kunci personal yang menyalin label/confidence deteksi orang, ditambah 11 atribut PPE:

KunciIsi
personal{ "label": "person", "confidence": <float> } — salinan hasil deteksi objek dasar.
safety_glasses, face_shield, gloves, safety_harness{ "label": "Yes"|"No"|"Unknown", "confidence": <float> }
head_protection, helmet_color, face_mask, protective_clothing, protective_clothing_color, footwear_type, work_context{ "label": "<salah satu nilai kelas>", "confidence": <float> } — daftar nilai per atribut ada di Konfigurasi — Atribut PPE.

Kunci personal berasal dari nama pipeline internal "Personal Protective Equipment Analytic" yang diambil kata pertamanya lalu di-lowercase (src/packages/multi_logics/config.hpp dan routines.hpp). Ini bukan nama yang dapat dikonfigurasi — perlakukan sebagai bagian tetap dari kontrak event.

Contoh Event per Sub-Analytic

{
  "analytic_id": "NFV4-PPE",
  "primary_text": "person",
  "secondary_text": "in",
  "pipeline_data": {
    "confidence": 0.86,
    "label": "person",
    "area_name": "Site Entrance",
    "direction": "in",
    "tracker_id": 5,
    "group_id": 0,
    "logic": "counting",
    "attributes": {
      "personal": { "label": "person", "confidence": 0.86 },
      "head_protection": { "label": "Hard helmet", "confidence": 0.92 },
      "protective_clothing": { "label": "Safety vest", "confidence": 0.88 }
    },
    "event_id": "1705314600-3a1f9d4c"
  }
}
{
  "analytic_id": "NFV4-PPE",
  "primary_text": "person",
  "secondary_text": "in",
  "pipeline_data": {
    "confidence": 0.82,
    "label": "person",
    "area_name": "Welding Bay",
    "direction": "in",
    "tracker_id": 9,
    "group_id": 0,
    "logic": "roi_counting",
    "attributes": {
      "personal": { "label": "person", "confidence": 0.82 },
      "face_shield": { "label": "Yes", "confidence": 0.89 },
      "gloves": { "label": "Yes", "confidence": 0.81 },
      "protective_clothing": { "label": "Coverall", "confidence": 0.84 }
    },
    "event_id": "1705314601-8b2c7e1a"
  }
}
{
  "analytic_id": "NFV4-PPE",
  "primary_text": "Restricted Area",
  "secondary_text": "120.000 s",
  "pipeline_data": {
    "confidence": 0.78,
    "label": "person",
    "area_name": "Restricted Area",
    "tracker_id": 12,
    "group_id": 0,
    "time_in": 1705314480000,
    "time_out": null,
    "time_alert": 1705314600000,
    "duration": 120.0,
    "logic": "dwelling",
    "attributes": {
      "personal": { "label": "person", "confidence": 0.78 },
      "head_protection": { "label": "Unknown", "confidence": 0.34 },
      "protective_clothing": { "label": "Safety vest", "confidence": 0.82 }
    },
    "event_id": "1705314600-1a2b3c4d"
  }
}
{
  "analytic_id": "NFV4-PPE",
  "primary_text": "Loading Dock",
  "secondary_text": "8",
  "pipeline_data": {
    "interval": 10,
    "area": "Loading Dock",
    "estimation": 8,
    "logic": "density",
    "detected": [
      {
        "tracker_id": 7,
        "group_id": 0,
        "bbox": { "top": 150, "left": 100, "width": 80, "height": 220 },
        "label": "person",
        "confidence": 0.84,
        "attributes": {
          "personal": { "label": "person", "confidence": 0.84 },
          "head_protection": { "label": "Hard helmet", "confidence": 0.9 },
          "protective_clothing": { "label": "Safety vest", "confidence": 0.86 }
        }
      }
    ],
    "event_id": "1705314600-9f4e2b7c"
  }
}

On this page