Reviewed-on: #7 Co-authored-by: Ibrahim Boubakri <ibrahim.boubakri@uqtr.ca> Co-committed-by: Ibrahim Boubakri <ibrahim.boubakri@uqtr.ca> |
||
|---|---|---|
| adapters | ||
| config | ||
| docs | ||
| mediamtx | ||
| sensor-manager | ||
| shared | ||
| .env.example | ||
| .gitignore | ||
| README.md | ||
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
- Architecture
- Repository layout
- Components
- Request routing
- Streaming lifecycle
- Workflow integration (VP)
- Services and ports
- Quick start
- Configuration
- API overview
- Development
- Roadmap
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:
/healthreports adapter configuration status - Adapter proxy: forwards
/rtsp/*→ rtsp-adapter; returns501for 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 /swaggeron 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_api → localhost: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).
- Register camera — store RTSP credentials / ONVIF profile in MongoDB
- Create stream — define a MediaMTX path name linked to the camera
- Start stream — adapter calls MediaMTX API; camera RTSP is pulled
- Play — front uses proxied HLS/WebRTC; VP uses
rtspPlayUrlon 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
Full platform (recommended)
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"
}
Related documentation
- RTSP adapter API details:
adapters/rtsp/docs/swagger.yaml - Platform orchestration:
../MedusInfra/docker-compose.local.yml - Front integration:
../MedusFront/src/services/SensorManagerService.ts