No description
Find a file
Ibrahim Boubakri efb880581a refactor_native (#7)
Reviewed-on: #7
Co-authored-by: Ibrahim Boubakri <ibrahim.boubakri@uqtr.ca>
Co-committed-by: Ibrahim Boubakri <ibrahim.boubakri@uqtr.ca>
2026-07-13 20:57:11 +02:00
adapters refactor_native (#7) 2026-07-13 20:57:11 +02:00
config feat: add ROS and native adapters with shared sensor-manager proxy (#4) 2026-06-30 22:11:50 +02:00
docs feat: add ROS and native adapters with shared sensor-manager proxy (#4) 2026-06-30 22:11:50 +02:00
mediamtx refactor_native (#7) 2026-07-13 20:57:11 +02:00
sensor-manager refactor: remove CreateCamera handler and related request structures from camera adapters (#6) 2026-07-13 18:04:06 +02:00
shared fix/refactor_sensormanager_functions (#5) 2026-07-08 16:26:13 +02:00
.env.example fix/refactor_sensormanager_functions (#5) 2026-07-08 16:26:13 +02:00
.gitignore feat: add ROS and native adapters with shared sensor-manager proxy (#4) 2026-06-30 22:11:50 +02:00
README.md fix/refactor_sensormanager_functions (#5) 2026-07-08 16:26:13 +02:00

SensorManagerGlobal

Coordination layer for sensor adapter proxying and runtime video streaming in the MedusAI platform.

This repository is the single entry point for physical and network sensors. It exposes a unified API (sensor-manager) and delegates protocol-specific work to adapters (RTSP today; ROS, native devices, and brokers planned).


Table of contents


Platform context

SensorManagerGlobal sits between the MedusFront UI and low-level streaming infrastructure. Business APIs such as authentication, sites, areas, and floors are owned by MedusEdgeBack; this module only routes sensor adapter traffic and hosts sensor runtime components.

flowchart LR
    subgraph Client
        FE[MedusFront]
    end

    subgraph MedusInfra["MedusInfra Docker"]
        NGINX["Nginx port 80"]
        SM["sensor-manager port 6000"]
        RTSP["rtsp-adapter port 8081"]
        MTX[MediaMTX]
        MONGO[(MongoDB)]
        S3[SeaweedFS]
    end

    subgraph External
        CAM[IP Camera RTSP]
        EDGE["MedusEdgeBack port 4001"]
        VP["VP_Backend port 3001"]
    end

    FE -->|"/sensor_api/*"| NGINX
    FE -->|"/hls/* /webrtc/*"| NGINX
    NGINX --> SM
    SM -->|"/rtsp/* proxy"| RTSP
    RTSP --> MONGO
    RTSP --> MTX
    RTSP --> S3
    MTX <-->|RTSP ingest / HLS out| CAM
    FE --> EDGE
    FE --> VP
    VP -->|ensure stream + rtspPlayUrl| RTSP

Architecture

Two-tier design: orchestration (sensor-manager) + adapters (protocol backends).

flowchart TB
    subgraph SensorManagerGlobal
        direction TB

        SM["sensor-manager<br/><i>Adapter routing</i>"]

        subgraph Adapters
            RTSP["adapters/rtsp<br/><i>Cameras, streams, ONVIF, recordings</i>"]
            ROS["adapters/ros<br/><i>planned</i>"]
            NAT["adapters/native<br/><i>planned</i>"]
            BRK["adapters/broker<br/><i>planned</i>"]
        end

        SHARED["shared/models<br/><i>Sensor types</i>"]
        MTXCFG["config/mediamtx.yml"]
        MTXIMG["mediamtx/ Docker image"]
    end

    SM --> RTSP
    SM -.-> ROS
    SM -.-> NAT
    SM -.-> BRK
    RTSP --> MTXCFG
    RTSP --> MTXIMG
    RTSP --> SHARED
    SM --> SHARED
Layer Responsibility
sensor-manager Reverse-proxies adapter APIs under /rtsp, /ros, /native, …
adapters/rtsp Camera CRUD, ONVIF discovery, MediaMTX path registration, HLS/WebRTC URLs, recordings
MediaMTX Ingest RTSP from cameras, republish as HLS / WebRTC / RTMP
shared/ Common Go sensor and streaming types shared across services

Repository layout

SensorManagerGlobal/
├── sensor-manager/          # Adapter proxy API
│   ├── cmd/server/
│   └── internal/
│       └── proxy/           # Reverse proxy to adapters
├── adapters/
│   └── rtsp/                # RTSP / ONVIF adapter (Go + Gin)
│       ├── cmd/server/
│       ├── internal/
│       │   ├── handlers/    # camera, stream, webhook, video, alerts
│       │   ├── services/
│       │   │   ├── streaming/   # MediaMTX client
│       │   │   ├── onvif/       # Camera discovery
│       │   │   └── storage/     # SeaweedFS recordings
│       │   └── docs/        # OpenAPI / Swagger
│       └── Dockerfile
├── shared/
│   └── models/              # BaseSensor and sensor runtime types
├── config/
│   └── mediamtx.yml         # MediaMTX paths, webhooks, recording
├── mediamtx/
│   ├── Dockerfile
│   └── start.sh
├── .env.example
└── README.md

Components

sensor-manager (port 6000)

  • Health: /health reports adapter configuration status
  • Adapter proxy: forwards /rtsp/* → rtsp-adapter; returns 501 for unimplemented adapters

adapters/rtsp (port 8081, internal)

  • Cameras: register IP cameras, ONVIF discover, profiles, sensor configs
  • Streams: create/start/stop MediaMTX paths; expose rtspPlayUrl, HLS, WebRTC URLs
  • Recordings & videos: schedule recording, list/download from SeaweedFS
  • Webhooks: MediaMTX lifecycle callbacks (ready, notready, recording)
  • Swagger: GET /swagger on the adapter (proxied via sensor-manager)

MediaMTX

Streaming relay. Ingests camera RTSP, outputs:

Output Typical use
HLS :8880 Browser preview in MedusFront (/hls/…)
WebRTC :8889 Low-latency preview (/webrtc/…)
RTSP :8554 VP workflow input (NetworkCameraInput)

HLS uses port 8880 (not 8888) to avoid conflict with SeaweedFS Filer in MedusInfra.


Request routing

How a front-end call reaches the RTSP adapter:

sequenceDiagram
    participant FE as MedusFront
    participant NX as Nginx
    participant SM as sensor-manager
    participant RT as rtsp-adapter

    FE->>NX: GET /sensor_api/rtsp/gateway_api/v1/camera
    NX->>SM: GET /rtsp/gateway_api/v1/camera
    Note over SM: Strip /rtsp prefix
    SM->>RT: GET /gateway_api/v1/camera
    RT-->>SM: JSON response
    SM-->>NX: JSON response
    NX-->>FE: JSON response

Vite dev proxy (local front on :3000): /sensor_apilocalhost:6000 (see MedusFront/vite.config.ts).


Streaming lifecycle

stateDiagram-v2
    [*] --> Registered
    Registered --> PathCreated: POST stream
    PathCreated --> Running: POST start
    Running --> Running: MediaMTX ingests RTSP
    Running --> Stopped: POST stop
    Stopped --> Running: POST start
    Running --> [*]: DELETE stream

API calls (full paths under /gateway_api/v1/):

Step Method Path
Register camera POST /camera
Create stream POST /stream
Start POST /stream/{id}/start
Stop POST /stream/{id}/stop
Delete DELETE /stream/{id}

While Running, clients receive rtspPlayUrl (VP), hlsUrl (browser), and webrtcUrl (low latency).

  1. Register camera — store RTSP credentials / ONVIF profile in MongoDB
  2. Create stream — define a MediaMTX path name linked to the camera
  3. Start stream — adapter calls MediaMTX API; camera RTSP is pulled
  4. Play — front uses proxied HLS/WebRTC; VP uses rtspPlayUrl on port 8554

Workflow integration (VP)

MedusFront ensures an RTSP path is running before starting a VP workflow:

sequenceDiagram
    participant FE as MedusFront
    participant SM as SensorManager
    participant MTX as MediaMTX
    participant VP as VP_Backend

    FE->>SM: ensureRTSPStream(sensorId)
    SM->>MTX: start path (via rtsp-adapter)
    MTX-->>SM: rtspPlayUrl
    SM-->>FE: stream ready
    FE->>VP: Start workflow (rtspPlayUrl in input ref)
    VP->>MTX: OpenCV reads RTSP
    VP->>VP: YOLO + visualization
    VP->>FE: Live dashboard (via MedusEdgeBack)

Relevant front services: MedusFront/src/services/SensorManagerService.ts
Relevant VP nodes: NetworkCameraInput, RtspInputNode in VP_Backend/lib/nodes.py


Services and ports

Service Host port Protocol Notes
sensor-manager 6000 HTTP Main API + adapter proxy
rtsp-adapter 8081 HTTP Internal (Docker network only)
MediaMTX RTSP 8554 RTSP/TCP Workflow + relay ingest
MediaMTX HLS 8880 HTTP Browser playback via /hls/
MediaMTX WebRTC 8889 HTTP/WS Browser playback via /webrtc/
MediaMTX RTMP 1935 RTMP Optional ingest
MediaMTX API 9997 HTTP Control / diagnostics
MongoDB 27017 TCP Shared medusai database
Nginx gateway 80 HTTP /sensor_api/ → sensor-manager

Quick start

From MedusInfra — starts MongoDB, SeaweedFS, MediaMTX, rtsp-adapter, sensor-manager, and Nginx:

cd ../MedusInfra
docker compose -f docker-compose.local.yml up -d --build

Health checks

# sensor-manager
curl http://localhost:6000/health

# Via Nginx (same path the front uses)
curl http://localhost/sensor_api/health

# RTSP adapter (via proxy)
curl http://localhost/sensor_api/rtsp/gateway_api/v1/health

# MediaMTX
curl http://localhost:9997/v3/config/global/get
curl http://localhost:9997/v3/paths/list

Swagger UI

When the stack is running:

http://localhost/sensor_api/rtsp/swagger

OpenAPI spec: adapters/rtsp/docs/swagger.yaml


Configuration

Copy the example env file for the sensor adapters. JWT values must match MedusEdgeBack because adapters validate tokens issued by MedusEdgeBack; the central sensor-manager service does not issue tokens or own site/area data.

cp .env.example .env

Key adapter variables (see .env.example for the full list):

Variable Purpose
MONGO_URI Adapter persistence for sensor/camera records in the shared medusai database
JWT_SECRET Used by adapters to validate MedusEdgeBack-issued tokens
MEDIAMTX_API_URL Internal MediaMTX control API
MEDIAMTX_HLS_BASE_URL Public HLS base for generated play URLs
MEDIAMTX_RTSP_BASE_URL Public RTSP base for rtspPlayUrl
SEAWEED_FILER_URL Recording storage

Docker Compose in MedusInfra mounts SensorManagerGlobal/.env into the adapters and sets adapter URLs for sensor-manager.


API overview

sensor-manager (direct or via /sensor_api/)

Method Path Description
GET /health Service + adapter status
* /rtsp/* Proxy → rtsp-adapter
* /ros/*, /native/* Proxy → protocol adapters
* /broker/* 501 — not implemented

rtsp-adapter (via /sensor_api/rtsp/gateway_api/v1/)

Group Examples
camera GET /camera, POST /camera/discover, POST /camera, GET /camera/:id/profiles
stream POST /stream, POST /stream/:id/start, POST /stream/:id/stop, GET /stream/:id/stats
recording GET /recording, DELETE /recording/:id
videos GET /videos, GET /videos/:id/download
alerts GET /alerts, POST /alerts/:id/resolve

Sites, areas, and floors are exposed by MedusEdgeBack under /api/site.


Development

Run sensor-manager locally

cd sensor-manager
export PORT=6000
export RTSP_ADAPTER_URL=http://localhost:8081
export NATIVE_ADAPTER_URL=http://localhost:8082
export ROS_ADAPTER_URL=http://localhost:8083
go run ./cmd/server

Run rtsp-adapter locally

cd adapters/rtsp
cp ../../.env.example ../../.env   # if not done yet
go mod tidy
go run ./cmd/server

Requires MongoDB, MediaMTX, and (optionally) SeaweedFS — easiest via MedusInfra Docker stack.

Build Docker images

Images are built from repo root context (see MedusInfra/docker-compose.local.yml):

docker compose -f ../MedusInfra/docker-compose.local.yml build sensor-manager rtsp-adapter mediamtx

Roadmap

Adapter Status Purpose
rtsp Active IP cameras, ONVIF, MediaMTX
ros 🔜 Planned ROS2 topic sensors
native 🔜 Planned USB / V4L2 devices
broker 🔜 Planned MQTT / Kafka ingress

Unimplemented adapter routes return:

{
  "error": "ros adapter is not yet available",
  "adapter": "ros",
  "status": "coming_soon"
}