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

## Architecture complète avec LoRaWAN

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                     Smart City Simulator (Python)                         │
│  Publie sur 3 brokers MQTT + REST vers OpenRemote                        │
└──────────┬────────────────────┬──────────────────────┬───────────────────┘
           │                    │                      │
           ▼                    ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│   EMQX Broker   │  │ Mosquitto Broker │  │  BunkerM Broker │
│   (port 11883)  │  │   (port 1883)   │  │   (port 1900)   │
└────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘
         │                       │                      │
         ▼                       ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│ IoT-Agent-EMQX  │  │IoT-Agent-Mosquitto│  │IoT-Agent-BunkerM │
│ Port: 4041      │  │ Port: 4042      │  │ Port: 4043      │
└────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘
         │                       │                      │
         └───────────────────────┴──────────────────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   Orion-LD Context  │
                    │   Broker (port 1026)│
                    │   MongoDB backend   │
                    └─────────┬───────────┘
                              │
                              │ Subscription → QuantumLeap
                              ▼
                    ┌─────────────────────┐
                    │   QuantumLeap       │
                    │   (port 8668)      │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   CrateDB           │
                    │   (ports 5432/4200)│
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │   Grafana          │
                    │   (port 3001)     │
                    └─────────────────────┘

═══════════════════════════════════════════════════════════════════════════════
                              LoRaWAN Layer
═══════════════════════════════════════════════════════════════════════════════

┌──────────────────┐         ┌──────────────────┐
│  Gateway LoRaWAN │  UDP    │  Gateway LoRaWAN │
│  (EU868)        │  1700   │  (EU868)        │
└────────┬─────────┘         └────────┬─────────┘
         │                            │
         ▼                            ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                        ChirpStack LoRaWAN Network Server                   │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐          │
│  │ chirpstack       │  │ gateway-bridge   │  │ rest-api         │          │
│  │ (port 8080)      │  │ (UDP 1700)       │  │ (port 8090)      │          │
│  └────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘          │
│           │                     │                      │                    │
│           ▼                     ▼                      ▼                    │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐          │
│  │ PostgreSQL       │  │ Redis            │  │ Mosquitto (MQTT) │          │
│  │ (chirpstack DB)  │  │ (cache)          │  │ (port 1883)      │          │
│  └──────────────────┘  └──────────────────┘  └────────┬─────────┘          │
└──────────────────────────────────────────────────────┬─────────────────────┘
                                                       │
                                                       ▼
                                              ┌──────────────────┐
                                              │  EMQX Broker     │
                                              │  (integration)   │
                                              └──────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                    The Things Stack LoRaWAN Network Server                  │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐          │
│  │ tts-stack         │  │ tts-postgres     │  │ tts-redis        │          │
│  │ (port 1885)      │  │ (TTN DB)         │  │ (cache)          │          │
│  └────────┬─────────┘  └──────────────────┘  └──────────────────┘          │
│           │                                                                 │
│           │ UDP 1700 (gateways)                                             │
│           │ MQTT 1883 (events)                                              │
│           │ HTTP 1884 (API)                                                 │
│           │ HTTP 1885 (Console)                                             │
└───────────┬─────────────────────────────────────────────────────────────────┘
            │
            ▼
   ┌──────────────────┐
   │  EMQX Broker     │
   │  (integration)   │
   └──────────────────┘

═══════════════════════════════════════════════════════════════════════════════
                              OpenRemote Manager
═══════════════════════════════════════════════════════════════════════════════

┌─────────────────────────────────────────────────────────────────────────────┐
│                        OpenRemote Manager (Artemis MQTT)                   │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐          │
│  │ Manager UI       │  │ Keycloak         │  │ PostgreSQL       │          │
│  │ (port 8080)      │  │ (port 8080)      │  │ (port 5432)      │          │
│  └──────────────────┘  └──────────────────┘  └──────────────────┘          │
│                                                                             │
│  Assets IOTSensor avec agentLink MQTT + location (GeoJSON Point)          │
│  Assets visualisés sur la carte Martinique (mapsettings.json)              │
└─────────────────────────────────────────────────────────────────────────────┘
```

## 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

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

4. **Subscription Orion-LD → QuantumLeap**
   - Notify URL: `http://smart-city-quantumleap:8668/v2/op/notify`

5. **QuantumLeap** stocke dans **CrateDB**
   - Table: `quantumleap.etairqualityobserved`

6. **Grafana** visualise les données
   - Datasource: `CrateDB-SmartCity`

7. **ChirpStack** gère les gateways et devices LoRaWAN
   - Gateway Bridge (UDP 1700) → ChirpStack → MQTT → EMQX
   - REST API (port 8090) pour gestion des devices/applications

8. **The Things Stack** gère les gateways et devices LoRaWAN (alternative)
   - Gateway (UDP 1700) → TTS Stack → MQTT/REST API
   - Console web (port 1885)

9. **OpenRemote** affiche les assets sur la map
   - Assets IOTSensor avec location GeoJSON
   - Agents MQTT pour mise à jour des valeurs

## Sous-domaines (Traefik)

### IoT Agents & Brokers
- `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)

### ChirpStack LoRaWAN
- `chirpstack.digitribe.fr` → ChirpStack Console (port 8080)
- `chirpstack-api.digitribe.fr` → ChirpStack REST API (port 8090)
- `chirpstack-ws.digitribe.fr` → Gateway Bridge WebSocket (port 3001)

### The Things Stack LoRaWAN
- `tts.digitribe.fr` → TTS Console (port 1885)
- `tts-api.digitribe.fr` → TTS REST API (port 1884)

### OpenRemote
- `openremote.digitribe.fr` → OpenRemote Manager (port 8080)

## 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)
