# Smart City Digital Twin - Data Flow Diagram (Updated 2026-05-06)

## Architecture évoluée : 1 IoT-Agent par broker MQTT

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                     Smart City Simulator (Python)                         │
│  Publie sur 3 brokers MQTT avec format IoT-Agent JSON                    │
└──────────┬────────────────────┬──────────────────────┬───────────────────┘
           │                    │                      │
           ▼                    ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│   EMQX Broker   │  │ Mosquitto Broker │  │  BunkerM Broker │
│   (port 11883)  │  │   (port 1883)   │  │   (port 1900)   │
│  Topic: smart-  │  │  Topic: smart-  │  │  Topic: smart-  │
│  city-api-key/  │  │  city-api-key/  │  │  city-api-key/  │
│  {id}/attrs     │  │  {id}/attrs     │  │  {id}/attrs     │
└────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘
         │                       │                      │
         ▼                       ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│ IoT-Agent-EMQX  │  │IoT-Agent-Mosquitto│  │IoT-Agent-BunkerM │
│ Port: 4041      │  │ Port: 4042      │  │ Port: 4043      │
│ Apikey: smart-  │  │ Apikey: smart-  │  │ Apikey: smart-  │
│ city-api-key    │  │ city-api-key    │  │ city-api-key    │
└────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘
         │                       │                      │
         └───────────────────────┴──────────────────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   Orion-LD Context  │
                    │   Broker (port 1026)│
                    │   MongoDB backend   │
                    └─────────┬───────────┘
                              │
                              │ Subscription (id: 69fbb09af55b82cad2a38008)
                              │ Forward to QuantumLeap
                              ▼
                    ┌─────────────────────┐
                    │   QuantumLeap       │
                    │   (port 8668)      │
                    │   /v2/op/notify    │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   CrateDB           │
                    │   (ports 5432/4200)│
                    │   DB: quantumleap  │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   Grafana          │
                    │   (port 3001)     │
                    │   Datasource:      │
                    │   CrateDB-SmartCity│
                    └─────────────────────┘
```

## Flux de données (Step-by-step)

1. **Simulator** publie sur 3 brokers MQTT (EMQX:11883, Mosquitto:1883, BunkerM:1900)
   - Topic: `smartcity-api-key/{device_id}/attrs`
   - Format: `{"NO2": 45.5, "temperature": 26.0, "humidity": 70.0}`

2. **3 IoT-Agents** (un par broker) reçoivent les messages
   - iot-agent-emqx (port 4041) ← EMQX
   - iot-agent-mosquitto (port 4042) ← Mosquitto
   - iot-agent-bunkerm (port 4043) ← BunkerM
   - Chaque IoT-Agent a le service `smartcity-api-key` configuré
   - Chaque IoT-Agent a le device `airquality_001` enregistré

3. **Orion-LD** reçoit les entités NGSI-v2
   - URL: `http://smart-city-orion-ld:1026`
   - Entité: `urn:ngsi-ld:AirQualityObserved:airquality_001`
   - Type: `AirQualityObserved`

4. **Subscription Orion-LD → QuantumLeap**
   - ID: `69fbb09af55b82cad2a38008`
   - Description: "Forward AirQualityObserved to QuantumLeap"
   - Notify URL: `http://smart-city-quantumleap:8668/v2/op/notify`
   - Attrs: NO2, temperature, humidity

5. **QuantumLeap** stocke dans **CrateDB**
   - Table: `quantumleap.etairqualityobserved`
   - Colonnes: entity_id, time_index, NO2, temperature, humidity

6. **Grafana** visualise les données
   - Datasource: `CrateDB-SmartCity` (ID: 23)
   - URL: `smart-city-cratedb:5432`
   - Database: `quantumleap`

## Services et Devices (provisionnés)

### IoT-Agent-EMQX (port 4041)
- Service: `smartcity-api-key` → Orion-LD (`http://smart-city-orion-ld:1026`)
- Device: `airquality_001` → `urn:ngsi-ld:AirQualityObserved:airquality_001`

### IoT-Agent-Mosquitto (port 4042)
- Service: `smartcity-api-key` → Orion-LD (`http://smart-city-orion-ld:1026`)
- Device: `airquality_001` → `urn:ngsi-ld:AirQualityObserved:airquality_001`

### IoT-Agent-BunkerM (port 4043)
- Service: `smartcity-api-key` → Orion-LD (`http://smart-city-orion-ld:1026`)
- Device: `airquality_001` → `urn:ngsi-ld:AirQualityObserved:airquality_001`

## Sous-domaines (Traefik)

- `iot-agent-emqx.digitribe.fr` → IoT-Agent-EMQX (port 4041)
- `iot-agent-mosquitto.digitribe.fr` → IoT-Agent-Mosquitto (port 4042)
- `iot-agent-bunkerm.digitribe.fr` → IoT-Agent-BunkerM (port 4043)
- `orion-ld.digitribe.fr` → Orion-LD (port 1026)
- `quantum-leap.digitribe.fr` → QuantumLeap (port 8668)
- `grafana.digitribe.fr` → Grafana (port 3001)

## Test du flux complet

```bash
# 1. Publier un message MQTT (simuler le simulateur)
mosquitto_pub -h localhost -p 11883 -t "smartcity-api-key/airquality_001/attrs" \
  -m '{"NO2": 50.5, "temperature": 30.0, "humidity": 90.0}'

# 2. Vérifier qu'Orion-LD a reçu l'entité
curl -s http://localhost:1026/v2/entities -w "\nHTTP %{http_code}\n"

# 3. Vérifier que QuantumLeap a reçu la notification
docker logs smart-city-quantumleap --tail 20 | grep -i "notify\|airquality"

# 4. Vérifier CrateDB
docker exec smart-city-cratedb crash -c "SELECT * FROM quantumleap.etairqualityobserved LIMIT 5;"

# 5. Vérifier Grafana
curl -s http://localhost:3001/api/datasources  -u admin:Digitribe972 | jq '.[] | select(.type=="postgres") | .name'
```

## Fichiers modifiés (2026-05-06)

- `docker-compose.iot-agent.yml` : 3 instances IoT-Agent (emqx, mosquitto, bunkerm)
- `docker-compose.orion-ld.yml` : Orion-LD avec MongoDB existant
- `docker-compose.quantumleap.yml` : Variables CRATE_HOST/PORT (fix)
- `simulator.py` : Publication sur 3 brokers avec format IoT-Agent
- `data-flow-diagram.md` : Ce fichier (mis à jour)
