Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 6 additions & 6 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ paths-ignore:
- "**/test_*.py"
- ".backups/**"
- "exported-assets/**"
- "android/build/**"
- "platforms/cpp/build/**"
- "apps/android/build/**"
- "apps/rpi-backend/cpp-audio/build/**"
- "**/node_modules/**"

# Paths to include (optional, analyze all if not specified)
paths:
- "modules/**"
- "rpi/**"
- "platforms/cpp/**"
- "android/app/src/**"
- "orchestration/mcp/**"
- "apps/rpi-backend/py-api/**"
- "apps/rpi-backend/cpp-audio/**"
- "apps/android/app/src/**"
22 changes: 11 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: flake8
continue-on-error: true
run: >
flake8 modules/ tests/ rpi/ api/ core/ agents/ services/ scripts/
flake8 orchestration/ tests/ apps/rpi-backend/ agents/ services/ scripts/
--max-line-length=120
--extend-ignore=E203,W503,W293,W291,E402,E302,E305,E501
--per-file-ignores='tests/*:F401,F811'
Expand All @@ -36,11 +36,11 @@ jobs:
- name: black --check
run: >
black --check --line-length 120
--exclude '/(\.git|\.venv|venv|build|android|platforms/cpp|Mia/Vehicle|web|\.backups|exported-assets)/'
--exclude '/(\.git|\.venv|venv|build|apps/android|apps/esp32|platforms/cpp|Mia/Vehicle|web|\.backups|exported-assets)/'
.
continue-on-error: true
- name: isort --check
run: isort --check --profile black --skip .venv --skip venv --skip android --skip web .
run: isort --check --profile black --skip .venv --skip venv --skip apps/android --skip web .
continue-on-error: true

python-test:
Expand All @@ -60,7 +60,7 @@ jobs:
- uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-cpython-${{ hashFiles('conanfile.py') }}
key: conan-cpython-${{ hashFiles('infra/conan/conanfile.py') }}
restore-keys: conan-cpython-
- name: Install bundled CPython via Conan
run: |
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
- uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }}
key: conan-${{ matrix.arch }}-${{ hashFiles('infra/conan/conanfile.py') }}
restore-keys: conan-${{ matrix.arch }}-
- name: Build
continue-on-error: true
Expand All @@ -128,19 +128,19 @@ jobs:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('android/**/*.gradle*', 'android/gradle-wrapper.properties') }}
key: gradle-${{ hashFiles('apps/android/**/*.gradle*', 'apps/android/gradle-wrapper.properties') }}
restore-keys: gradle-
- name: Build debug APK
continue-on-error: true
run: |
cd android
cd apps/android
chmod +x gradlew 2>/dev/null || true
./gradlew assembleDebug --no-daemon || echo "Android build completed with warnings"
- uses: actions/upload-artifact@v4
if: success()
with:
name: android-debug-apk
path: android/app/build/outputs/apk/debug/app-debug.apk
path: apps/android/app/build/outputs/apk/debug/app-debug.apk

esp32-build:
name: ESP32 Build
Expand All @@ -153,7 +153,7 @@ jobs:
- name: Check for PlatformIO config
id: check
run: |
if [ -f esp32/platformio.ini ]; then
if [ -f apps/esp32/platformio.ini ]; then
echo "has_pio=true" >> $GITHUB_OUTPUT
else
echo "has_pio=false" >> $GITHUB_OUTPUT
Expand All @@ -162,11 +162,11 @@ jobs:
if: steps.check.outputs.has_pio == 'true'
with:
path: ~/.platformio
key: pio-${{ hashFiles('esp32/platformio.ini') }}
key: pio-${{ hashFiles('apps/esp32/platformio.ini') }}
- name: Build with PlatformIO
if: steps.check.outputs.has_pio == 'true'
continue-on-error: true
run: |
pip install platformio
cd esp32
cd apps/esp32
pio run || echo "ESP32 build completed with warnings"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ Dockerfile.prod
build-Debug/
build-Release/

# Git worktrees (isolated feature workspaces)
.worktrees/

# Temporary pip cache files
=*

Expand Down
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ repos:
hooks:
- id: black
language_version: python3.11
exclude: ^(\.backups/|exported-assets/|android/|platforms/cpp/)
exclude: ^(\.backups/|exported-assets/|apps/android/|platforms/cpp/)

# Python import sorting
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black"]
exclude: ^(\.backups/|exported-assets/|android/|platforms/cpp/)
exclude: ^(\.backups/|exported-assets/|apps/android/|platforms/cpp/)

# Python linting
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
args: ["--max-line-length=120", "--extend-ignore=E203,W503"]
exclude: ^(\.backups/|exported-assets/|android/|platforms/cpp/|Mia/Vehicle/)
exclude: ^(\.backups/|exported-assets/|apps/android/|platforms/cpp/|Mia/Vehicle/)

# YAML validation
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-yaml
exclude: ^(android/|\.github/workflows/)
exclude: ^(apps/android/|\.github/workflows/)
- id: end-of-file-fixer
exclude: ^(\.backups/|exported-assets/)
- id: trailing-whitespace
Expand Down
130 changes: 130 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# MIA Architecture & Repository Structure

## Repository Organization

MIA is a distributed vehicle telemetry and IoT control system with four key organizational layers:

### 1. Applications (`apps/`)

Runtime applications targeting specific platforms:

- **`apps/android/`** - Android companion app (Kotlin + Jetpack Compose, Hilt DI, Room, WebSocket)
- **`apps/rpi-backend/py-api/`** - Python FastAPI server on Raspberry Pi 4B (ZeroMQ broker, REST/WebSocket, MCP bridge)
- **`apps/rpi-backend/cpp-audio/`** - C++ audio processing for beat detection, FFT optimization, DSP
- **`apps/esp32/`** - ESP32 firmware (PlatformIO, sensor drivers, BLE, OBD-II emulation)

### 2. Orchestration (`orchestration/`)

Multi-agent orchestration and MCP microservices:

- **`orchestration/mia-agents/`** - AI agents configuration, agent definitions, skill orchestration
- **`orchestration/mcp/`** - MCP server definitions, microservice configurations, framework code
- **`orchestration/mcp/prompts/`** - MIA-specific prompts for voice commands, workflows, domain knowledge

Includes:
- Core orchestrator (routes user commands to specialized agents)
- Service discovery (health checks, registry)
- AI audio assistant (Whisper STT, ElevenLabs TTS, Spotify)
- Automotive bridge (OBD-II, Citroën C4 PSA PIDs)
- Hardware bridge (GPIO abstraction)
- Security scanners and platform controllers

### 3. Infrastructure (`infra/`)

Deployment, containerization, and runtime configuration:

- **`infra/docker/`** - Docker Compose (dev/prod), Dockerfiles for each service
- **`infra/systemd/`** - Systemd service files for RPi deployment
- **`infra/conan/`** - Conan profiles, cross-compilation, package recipes
- **`infra/deploy/`** - Deployment scripts (RPi, ESP32, AWS/K8s), SSH/SCP/Ansible configs

### 4. Tests & Tools (`tests/`, `tools/`)

Cross-cutting concerns:

- **`tests/unit/`** - Unit tests per platform (Android, RPi, ESP32)
- **`tests/integration/`** - Integration test scenarios and fixtures (voice→LED, OBD telemetry, etc.)
- **`tools/ci/`** - CI helper scripts, linting, validation
- **`tools/local-dev/`** - Developer scripts (build all, sync assets, flash firmware, start stack)

## Data Flow

```
┌─────────────────────────────────────────────────────────────┐
│ Android App (apps/android/) │
│ • User speaks voice command │
│ • Sends intent via REST/WebSocket │
└──────────────────────┬──────────────────────────────────────┘
│ HTTP/WebSocket (8000)
┌──────────────────────▼──────────────────────────────────────┐
│ RPi Python API (apps/rpi-backend/py-api/) │
│ • FastAPI server + ZeroMQ ROUTER broker (5555) │
│ • Routes commands to MCP modules │
│ • Real-time telemetry via PUB/SUB (5556) │
└──────┬──────────┬──────────────┬──────────┬─────────────────┘
│ │ │ │
┌───▼─┐ ┌─────▼─┐ ┌──────────▼──┐ ┌────▼────┐
│GPIO │ │Serial │ │OBD Worker │ │Orchestr │
│ │ │Bridge │ │(Citroen C4) │ │ (MCP) │
└─────┘ └───┬───┘ └─────────────┘ └────┬────┘
│ │
┌──────▼─────┐ ┌─────▼──────────┐
│ ESP32/MCU │ │ AI Agents │
│ Sensors │ │ (orchestr/ │
│ BLE │ │ mia-agents/) │
└────────────┘ └────────────────┘
```

## Key Patterns

### Messaging Layer
- **Broker**: ZeroMQ ROUTER-DEALER on port 5555 (workers register as DEALER)
- **Pub/Sub**: ZeroMQ PUB/SUB on port 5556 (real-time telemetry to subscribers)
- **MCP Modules**: Microservices under `orchestration/mcp/` handle domain logic

### Testing Strategy
- **Unit tests**: Per-platform, isolated to `tests/unit/android|rpi|esp32/` (corresponding to `apps/` platforms)
- **Integration tests**: Named by business flow (e.g., `voice_command_led_brightness/`), located in `tests/integration/scenarios/`
- **Markers**: `@pytest.mark.hardware`, `.integration`, `.slow` for selective execution

### CI/CD
- **Workflows**: Separate files per platform in `.github/workflows/`
- **Path-based triggers**: Each workflow only runs on changes to its platform
- **Artifact storage**: Test reports, coverage, build logs in `.artifacts/` (gitignored)

## Development Workflow

### Local Setup
```bash
# From repo root:
./tools/local-dev/start-dev-stack.sh # Docker + RPi backend
./tools/ci/lint-all.sh # Pre-commit checks
pytest tests/ -m "not hardware" # Run non-hardware tests
```

### Building a New Feature
1. Create feature branch: `git checkout -b feature/xyz`
2. Make changes in relevant `apps/`, `orchestration/`, or `infra/` subdirectory
3. Write tests in corresponding `tests/` location
4. Run local validation: `./tools/ci/lint-all.sh && pytest tests/`
5. Push and create PR targeting `main`
6. CI runs platform-specific jobs based on changed paths

### Deployment
- **Development**: `docker compose -f infra/docker/docker-compose.dev.yml up`
- **Production RPi**: `./infra/deploy/rpi/deploy.sh` (copies to `/opt/mia/`, starts systemd services)
- **ESP32**: `./infra/deploy/esp32/flash.sh` (uses platformio to upload firmware)

## Migration Notes

This structure was established to support:
- Clear separation of concerns (runtime vs. orchestration vs. infrastructure)
- Scalability (easy to add new platforms, devices, or regions)
- CI/CD path-based triggering (changes in `apps/android/` don't trigger full C++ rebuild)
- Multi-team development (frontend, backend, embedded, infrastructure teams each own clear domains)

Legacy files still being consolidated:
- Old `core/`, `services/`, `rpi/` directories being merged into `apps/rpi-backend/`
- Old `platforms/cpp/` moving to `apps/rpi-backend/cpp-audio/`
- Old `docker/`, `deploy/` being consolidated under `infra/`
- `modules/` becoming `orchestration/mcp/` (preserving hyphenated module names)
28 changes: 14 additions & 14 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,23 @@ cd android && ./gradlew assembleDebug
### Docker

```bash
docker compose up # full stack (orchestrator, MQTT, Postgres, Redis, Grafana)
docker compose -f docker-compose.dev.yml up # dev mode with volume mounts
docker compose -f infra/docker/docker-compose.yml up # full stack (orchestrator, MQTT, Postgres, Redis, Grafana)
docker compose -f infra/docker/docker-compose.dev.yml up # dev mode with volume mounts
```

## Architecture

### Messaging Layer (ZeroMQ)

The central nervous system is a ZeroMQ ROUTER-DEALER broker (`core/messaging/broker.py`) on port 5555. Workers (GPIO, serial bridge, OBD) connect as DEALER sockets. The FastAPI server also connects as a DEALER to relay HTTP/WebSocket requests.
The central nervous system is a ZeroMQ ROUTER-DEALER broker (`apps/rpi-backend/shared/messaging/broker.py`) on port 5555. Workers (GPIO, serial bridge, OBD) connect as DEALER sockets. The FastAPI server also connects as a DEALER to relay HTTP/WebSocket requests.

A separate PUB/SUB channel on port 5556 distributes real-time MCU telemetry from the serial bridge to subscribers (OBD worker, etc.).

### REST/WebSocket Gateway

`api/main.py` runs FastAPI on port 8000 with REST endpoints for GPIO control, device listing, telemetry, and a WebSocket endpoint (`/ws`) for real-time streaming. API key auth in `api/auth/`.
`apps/rpi-backend/py-api/api/main.py` runs FastAPI on port 8000 with REST endpoints for GPIO control, device listing, telemetry, and a WebSocket endpoint (`/ws`) for real-time streaming. API key auth in `apps/rpi-backend/py-api/api/auth/`.

### MCP Modules (`modules/`)
### MCP Modules (`orchestration/mcp/modules/`)

Each subdirectory is an MCP (Model Context Protocol) microservice:
- **core-orchestrator** - Routes user commands to appropriate MCP modules
Expand All @@ -79,20 +79,20 @@ Each subdirectory is an MCP (Model Context Protocol) microservice:
- **automotive-mcp-bridge** / **citroen-c4-bridge** - Vehicle OBD-II interface
- **hardware-bridge** - Hardware abstraction

The shared MCP framework lives in `modules/shared/mcp_framework.py`. Note: copies still exist in individual module directories (known duplication being consolidated).
The shared MCP framework lives in `orchestration/mcp/modules/shared/mcp_framework.py`. Note: copies still exist in individual module directories (known duplication being consolidated).

### Hardware Layer

- `hardware/gpio_worker.py` - GPIO control with simulation fallback when RPi.GPIO unavailable
- `hardware/serial_bridge.py` - USB serial to ZeroMQ bridge for ESP32/Arduino
- `hardware/sensor_drivers/` - I2C/SPI sensor drivers (BME280, DHT, etc.)
- `rpi/hardware/` - Raspberry Pi-specific implementations
- `apps/rpi-backend/py-api/hardware/gpio_worker.py` - GPIO control with simulation fallback when RPi.GPIO unavailable
- `apps/rpi-backend/py-api/hardware/serial_bridge.py` - USB serial to ZeroMQ bridge for ESP32/Arduino
- `apps/rpi-backend/py-api/hardware/` - I2C/SPI sensor drivers (BME280, DHT, etc.)
- `apps/rpi-backend/cpp-audio/` - C++ audio and hardware implementations for RPi

### OBD-II Digital Twin

`services/obd_worker.py` implements a Digital Twin: physical potentiometers on an MCU drive an ELM327 emulator that responds to real OBD-II diagnostic tools with mapped engine parameters. Telemetry flows: MCU -> serial bridge -> ZMQ PUB -> OBD worker -> virtual PTY -> diagnostic tool.
`apps/rpi-backend/py-api/services/obd_worker.py` implements a Digital Twin: physical potentiometers on an MCU drive an ELM327 emulator that responds to real OBD-II diagnostic tools with mapped engine parameters. Telemetry flows: MCU -> serial bridge -> ZMQ PUB -> OBD worker -> virtual PTY -> diagnostic tool.

### Android App (`android/`)
### Android App (`apps/android/`)

Kotlin + Jetpack Compose with Hilt DI, Room DB, Retrofit/OkHttp, WebSocket. Features: BLE scanning, ANPR, dashboard recording, real-time telemetry charts.

Expand All @@ -106,11 +106,11 @@ FlatBuffers schemas in `schemas/` (main: `mia.fbs`) and `protos/` define message
- **pytest.ini**: asyncio_mode=auto, strict markers, test discovery in `tests/`
- **Flake8**: max-line-length=120, extends E203/W503 ignored
- **Black + isort**: isort uses `--profile black`
- **Pre-commit excludes**: `.backups/`, `exported-assets/`, `android/`, `platforms/cpp/` from Python linters
- **Pre-commit excludes**: `.backups/`, `exported-assets/`, `apps/android/`, `platforms/cpp/` from Python linters

## Deployment

Production target is `/opt/mia/` on Raspberry Pi. Systemd services defined in `services/*.service` (zmq-broker, mia-api, mia-gpio-worker, mia-serial-bridge, mia-obd-worker, mia-citroen-bridge, etc.). Deploy with `scripts/deploy-raspberry-pi.sh`. The ZMQ broker must start before other services.
Production target is `/opt/mia/` on Raspberry Pi. Systemd services defined in `infra/systemd/*.service` (zmq-broker, mia-api, mia-gpio-worker, mia-serial-bridge, mia-obd-worker, mia-citroen-bridge, etc.). Deploy with `infra/deploy/rpi/deploy.sh`. The ZMQ broker must start before other services.

## Conventions

Expand Down
6 changes: 3 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ MIA is a distributed control system designed for Raspberry Pi 4B as the primary
- `hardware/`: Arduino/ESP32 drivers and GPIO control
- `api/`: FastAPI application and WebSocket handlers
- `schemas/`: FlatBuffers schema definitions
- `android/`: Android app (native or Flutter)
- `apps/android/`: Android app (native or Flutter)
- [x] Set up CI/CD pipeline (GitHub Actions) with ARM64 support
- [x] Docker Compose configuration for local development and RPi deployment

Expand Down Expand Up @@ -563,8 +563,8 @@ Shared CPython bootstrap module for Android development tools.
### Files
| File | Purpose |
|------|---------|
| `android/tools/lib/cpython_bootstrap.py` | Shared bootstrap module |
| `android/tools/bootstrap-obd.py` | OBD-II simulator tool |
| `apps/android/tools/lib/cpython_bootstrap.py` | Shared bootstrap module |
| `apps/android/tools/bootstrap-obd.py` | OBD-II simulator tool |

---

Expand Down
25 changes: 0 additions & 25 deletions api/auth/__init__.py

This file was deleted.

Loading
Loading