Project Structure

Understanding the directory layout helps you navigate the codebase, contribute effectively, and customise RosFit for your use case.

Overview

The RosFit repository is organised as a monorepo. Each service lives in its own top-level directory with its own dependencies and Dockerfile.

rosfit/
├── bridge/                  # Robot-side MQTT bridge (Python)
│   ├── rosfit_bridge/
│   │   ├── __init__.py
│   │   ├── bridge.py        # Core bridge logic
│   │   ├── config.py        # YAML config parser
│   │   ├── mqtt_client.py   # MQTT connection manager
│   │   ├── ros_client.py    # ROS 2 subscriber/publisher
│   │   ├── shadow.py        # Device shadow sync
│   │   └── ota.py           # OTA update handler
│   ├── tests/
│   ├── pyproject.toml
│   └── Dockerfile
├── api/                     # FastAPI backend
│   ├── app/
│   │   ├── __init__.py
│   │   ├── main.py          # App entrypoint & middleware
│   │   ├── models/          # SQLAlchemy / Pydantic models
│   │   ├── routes/          # REST endpoints
│   │   │   ├── devices.py
│   │   │   ├── commands.py
│   │   │   ├── telemetry.py
│   │   │   ├── shadows.py
│   │   │   ├── ota.py
│   │   │   └── fleet.py
│   │   ├── services/        # Business logic
│   │   ├── auth/            # JWT & API key auth
│   │   └── ws/              # WebSocket handlers
│   ├── tests/
│   ├── requirements.txt
│   └── Dockerfile
├── handler/                 # MQTT message consumer
│   ├── rosfit_handler/
│   │   ├── __init__.py
│   │   ├── consumer.py      # MQTT subscription loop
│   │   ├── processors/      # Per-topic message processors
│   │   │   ├── telemetry.py # Persist to TimescaleDB
│   │   │   ├── shadow.py    # Update Redis shadow
│   │   │   ├── status.py    # Device status tracker
│   │   │   └── ota.py       # OTA progress handler
│   │   └── db.py            # Database connection pool
│   ├── tests/
│   ├── requirements.txt
│   └── Dockerfile
├── dashboard/               # React frontend (Vite + TypeScript)
│   ├── src/
│   │   ├── components/      # Reusable UI components
│   │   ├── pages/           # Route pages
│   │   ├── hooks/           # Custom React hooks
│   │   ├── services/        # API client & WebSocket
│   │   ├── stores/          # Zustand state management
│   │   └── types/           # TypeScript type definitions
│   ├── public/
│   ├── package.json
│   ├── vite.config.ts
│   └── Dockerfile
├── config/                  # Shared configuration
│   ├── emqx/
│   │   ├── acl.conf         # MQTT ACL rules
│   │   └── emqx.conf        # Broker settings
│   ├── certs/               # TLS certificates (gitignored)
│   │   └── .gitkeep
│   └── examples/
│       ├── bridge.yaml      # Example bridge config
│       └── .env.example     # Example environment file
├── migrations/              # Database migrations (Alembic)
│   ├── alembic.ini
│   ├── env.py
│   └── versions/
│       ├── 001_initial.py
│       ├── 002_telemetry_hypertable.py
│       └── 003_device_shadows.py
├── docker/                  # Additional Dockerfiles
│   ├── docker-compose.yml
│   ├── docker-compose.prod.yml
│   └── nginx.conf           # Reverse proxy config
├── docs/                    # Documentation site (this site)
├── .env.example
├── docker-compose.yml       # Development compose file
├── Makefile
└── README.md

Bridge

The bridge/ directory contains the robot-side Python package that runs on each device. It connects to the local ROS 2 network and forwards messages to the MQTT broker.

  • bridge.py — Orchestrates the ROS 2 ↔ MQTT mapping. Reads the YAML config, sets up subscribers and publishers, and manages the message loop.
  • config.py — Parses bridge.yaml, validates topic mappings, and resolves environment variable substitutions.
  • mqtt_client.py — Manages the MQTT connection lifecycle: connect, reconnect, TLS, authentication, and last-will messages.
  • ros_client.py — Creates ROS 2 subscribers and publishers dynamically based on the topic mapping configuration.
  • shadow.py — Implements the device shadow protocol. Reports the current state and applies desired state changes received from the cloud.
  • ota.py — Handles over-the-air firmware update commands. Downloads artefacts from MinIO, verifies checksums, and applies updates.

Install it on any machine with ROS 2:

pip install rosfit-bridge

API

The api/ directory contains the FastAPI backend that serves the REST API and WebSocket endpoints.

  • models/ — SQLAlchemy ORM models for devices, commands, telemetry records, and user accounts. Pydantic schemas for request/response validation.
  • routes/ — One module per resource: devices, commands, telemetry, shadows, OTA, and fleet. Each defines the endpoint handlers.
  • services/ — Business logic separated from HTTP concerns. Handles command routing, telemetry aggregation, and shadow conflict resolution.
  • auth/ — JWT token issuance and verification, API key validation, and role-based permission checks.
  • ws/ — WebSocket handlers for real-time telemetry streaming and live device status updates.

The API starts on port 8000 by default and serves the OpenAPI spec at /docs.

Message Handler

The handler/ directory contains the MQTT message consumer that runs as a background service. It subscribes to all rosfit/# topics on the broker and processes incoming messages.

  • consumer.py — Connects to EMQX, subscribes to wildcard topics, and routes messages to the appropriate processor based on the topic pattern.
  • processors/telemetry.py — Parses telemetry payloads and inserts them into TimescaleDB hypertables for time-series queries.
  • processors/shadow.py — Updates the reported state in Redis and computes diffs against the desired state.
  • processors/status.py — Tracks device online/offline status using MQTT last-will and keepalive messages.
  • processors/ota.py — Monitors OTA update progress reports and updates the rollout status in the database.

The handler has no exposed ports — it communicates exclusively through MQTT and the database.

Dashboard

The dashboard/ directory contains the React frontend built with Vite and TypeScript.

  • components/ — Reusable UI components: device cards, telemetry charts (Recharts), command forms, fleet map (Leaflet), and status indicators.
  • pages/ — Route-level pages: fleet overview, device detail, command console, OTA management, and settings.
  • hooks/ — Custom hooks for WebSocket subscriptions, API queries (React Query), and responsive layout.
  • services/ — API client (Axios) and WebSocket connection manager.
  • stores/ — Zustand stores for global state: selected device, active filters, user preferences.

The dashboard connects to the API over HTTP and receives real-time updates over WebSocket. It runs on port 3000.

Configuration

The config/ directory contains shared configuration that is mounted into Docker containers.

  • emqx/acl.conf — MQTT access control list. Restricts which devices can publish or subscribe to which topics, preventing cross-device access.
  • emqx/emqx.conf — EMQX broker settings: listeners, authentication backends, rate limits, and clustering.
  • certs/ — Directory for TLS certificates. Gitignored by default. Generate certs with rosfit certs generate or place your own CA-signed certificates here.
  • examples/ — Example configuration files for new users. The bridge.yaml shows a minimal topic mapping, and .env.example documents all environment variables.

The migrations/ directory uses Alembic to manage database schema evolution. Run migrations with:

alembic upgrade head

The docker/ directory contains production-oriented compose files and an Nginx reverse proxy config for TLS termination and routing.