From fb5b98043c4ba35c71e209c0196f57a880050ff6 Mon Sep 17 00:00:00 2001 From: Eric FELIXINE Date: Mon, 4 May 2026 17:43:08 -0400 Subject: [PATCH] Add data flow diagram (Mermaid MD, HTML, PDF) for Smart City Digital Twin --- data-flow-diagram.html | 464 +++++++++++++++++++++++++++++++++++++++++ data-flow-diagram.md | 191 +++++++++++++++++ data-flow-diagram.pdf | Bin 0 -> 22962 bytes 3 files changed, 655 insertions(+) create mode 100644 data-flow-diagram.html create mode 100644 data-flow-diagram.md create mode 100644 data-flow-diagram.pdf diff --git a/data-flow-diagram.html b/data-flow-diagram.html new file mode 100644 index 00000000..2c16f4f4 --- /dev/null +++ b/data-flow-diagram.html @@ -0,0 +1,464 @@ + + + + + + Smart City Digital Twin - Flux de Données + + + + +
+ +
+
+
+

Smart City Digital Twin — Flux de Données

+
+

Martinique • Simulator → Brokers → Context Brokers → Visualization

+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + 📡 COUCHE 1 : SOURCES DE DONNÉES + + + + + Smart City Simulator + Python • 10 capteurs + MQTT + REST API + + + 📡 COUCHE 2 : MQTT BROKERS + + + + + EMQX + Port 11883 (MQTT) + + + + + Mosquitto + Port 1883 (MQTT) + + + + + BunkerM + Port 1900 (MQTTS) + + + 🔄 COUCHE 3 : CONTEXT BROKERS (NGSI-LD) + + + + + Orion-LD + NGSI-LD + Port 1026 + Entities: Traffic, Air + + + + + Stellio + NGSI-LD + Port 8080 + 14 payloads entities + + + + + FROST-Server + SensorThings API + 21k+ observations + PostgreSQL+Timescale + + + 🏠 COUCHE 4 : PLATEFORME IOT (OpenRemote) + + + + + OpenRemote Manager + Realm: Smart City + 33 assets IoT + Port 8080 + Keycloak + + + + + Keycloak + Auth OpenID + + + 💾 COUCHE 5 : STOCKAGE & MÉTRIQUES + + + + + InfluxDB + IoT Data Bucket + + + + + Prometheus + Metrics + Alerting + + + + + GeoServer + WMS/WFS + PostGIS + + + 📊 COUCHE 6 : VISUALISATION & ANALYSE + + + + + Grafana + Dashboards + Datasources: + InfluxDB, FROST, Orion + + + + + MapStore + Cartographie + Sources: + GeoServer WMS + + + + + OpenRemote UI + Manager Interface + Realm: Smart City + + + + + + MQTT + + + + + + + + NGSI-LD + + + + + + + + REST API + + + + HTTP + + + + Query + + + + + + + + WMS/WFS + + + + DB Sync + + + + API Query + + + + Metrics + + + Légende + + + Source de données + + + MQTT Broker + + + Context Broker + + + IoT Platform + + + Stockage / Métriques + + + Visualisation + + + Flux de données + + + MQTT + + + REST API + + +
+ + +
+
+
+
+

Sources & Simulator

+
+
    +
  • • Smart City Simulator (Python)
  • +
  • • 10 capteurs : Traffic, Air, Parking, Noise, Weather, Light
  • +
  • • Intervalle : 10 secondes
  • +
  • • Protocoles : MQTT + REST API
  • +
+
+ +
+
+
+

MQTT Brokers

+
+
    +
  • • EMQX : Port 11883 (public)
  • +
  • • Mosquitto : Port 1883 (Traefik)
  • +
  • • BunkerM : Port 1900 (TLS)
  • +
  • • OpenRemote : Port 1883 (interne)
  • +
+
+ +
+
+
+

Context Brokers (NGSI-LD)

+
+
    +
  • • Orion-LD : 10 entités NGSI-LD
  • +
  • • Stellio : 14 payloads entités
  • +
  • • FROST-Server : 21k+ observations
  • +
  • • Smart Data Models utilisés
  • +
+
+ +
+
+
+

OpenRemote Platform

+
+
    +
  • • Realm : Smart City Martinique
  • +
  • • 33 assets IoT configurés
  • +
  • • Keycloak pour l'authentification
  • +
  • • REST API pour les capteurs
  • +
+
+ +
+
+
+

Stockage & Métriques

+
+
    +
  • • InfluxDB : Bucket iot_data
  • +
  • • Prometheus : Metrics brokers
  • +
  • • GeoServer : PostGIS + WMS
  • +
  • • PostgreSQL : OpenRemote + FROST
  • +
+
+ +
+
+
+

Visualisation & Analyse

+
+
    +
  • • Grafana : Dashboards (port 3001)
  • +
  • • MapStore : Cartographie WMS
  • +
  • • OpenRemote UI : Manager Smart City
  • +
  • • Datasources : InfluxDB, FROST, Orion
  • +
+
+
+ + + +
+ + diff --git a/data-flow-diagram.md b/data-flow-diagram.md new file mode 100644 index 00000000..80bcd910 --- /dev/null +++ b/data-flow-diagram.md @@ -0,0 +1,191 @@ +# Smart City Digital Twin — Diagramme des Flux de Données + +## Vue d'ensemble + +Ce diagramme illustre le flux complet des données IoT du simulateur vers les différentes couches de traitement, de stockage et de visualisation. + +--- + +## Diagramme Mermaid + +```mermaid +graph TB + %% ===== COUCHE 1 : SOURCES DE DONNÉES ===== + subgraph Sources["📡 COUCHE 1 : SOURCES DE DONNÉES"] + SIM[Smart City Simulator
Python • 10 capteurs
MQTT + REST API] + end + + %% ===== COUCHE 2 : MQTT BROKERS ===== + subgraph Brokers["📡 COUCHE 2 : MQTT BROKERS"] + EMQX[EMQX
Port 11883
MQTT] + MOSQ[Mosquitto
Port 1883
MQTT] + BUNKER[BunkerM
Port 1900
MQTTS] + end + + %% ===== COUCHE 3 : CONTEXT BROKERS (NGSI-LD) ===== + subgraph Context["🔄 COUCHE 3 : CONTEXT BROKERS (NGSI-LD)"] + ORION[Orion-LD
NGSI-LD
Port 1026
10 entités] + STELLIO[Stellio
NGSI-LD
Port 8080
14 payloads] + FROST[FROST-Server
SensorThings API
Port 8080
21k+ observations] + end + + %% ===== COUCHE 4 : PLATEFORME IoT ===== + subgraph IoT["🏠 COUCHE 4 : PLATEFORME IoT (OpenRemote)"] + OR[OpenRemote Manager
Realm: Smart City
33 assets IoT
Port 8080] + KC[Keycloak
Auth OpenID
Token endpoint] + end + + %% ===== COUCHE 5 : STOCKAGE & MÉTRIQUES ===== + subgraph Storage["💾 COUCHE 5 : STOCKAGE & MÉTRIQUES"] + INFLUX[InfluxDB
IoT Data Bucket
Port 8086] + PROM[Prometheus
Metrics + Alerting
Port 9090] + GEO[GeoServer
WMS/WFS + PostGIS
Port 8080] + end + + %% ===== COUCHE 6 : VISUALISATION & ANALYSE ===== + subgraph Viz["📊 COUCHE 6 : VISUALISATION & ANALYSE"] + GRAF[Grafana
Dashboards
Port 3001
Datasources: InfluxDB, FROST, Orion] + MAP[MapStore
Cartographie
WMS/WFS
GeoServer] + ORUI[OpenRemote UI
Manager Interface
Realm: Smart City] + end + + %% ===== FLUX DE DONNÉES ===== + + %% Simulator → MQTT Brokers + SIM -->|MQTT| EMQX + SIM -->|MQTT| MOSQ + SIM -->|MQTTS| BUNKER + + %% MQTT Brokers → Context Brokers + EMQX -->|NGSI-LD| ORION + EMQX -->|NGSI-LD| STELLIO + EMQX -->|SensorThings| FROST + + %% Simulator → OpenRemote (REST) + SIM -.->|REST API| OR + OR -.-> KC + + %% Simulator → InfluxDB + SIM -->|HTTP| INFLUX + + %% Context Brokers → Visualization + ORION -->|Query| GRAF + STELLIO -->|Query| GRAF + FROST -->|Query| GRAF + + %% Context Brokers → GeoServer (DB Sync) + ORION -.->|PostGIS| GEO + STELLIO -.->|PostGIS| GEO + FROST -.->|PostGIS| GEO + + %% GeoServer → MapStore + GEO -->|WMS/WFS| MAP + + %% OpenRemote → Grafana + OR -->|API Query| GRAF + + %% All → Prometheus (Metrics) + EMQX -.->|Metrics| PROM + ORION -.->|Metrics| PROM + STELLIO -.->|Metrics| PROM + OR -.->|Metrics| PROM + + %% Style + classDef simulator fill:#1e293b,stroke:#fb923c,stroke-width:2px,color:#fff + classDef broker fill:#0f172a,stroke:#22d3ee,stroke-width:2px,color:#fff + classDef context fill:#0f172a,stroke:#34d399,stroke-width:2px,color:#fff + classDef iot fill:#0f172a,stroke:#a78bfa,stroke-width:2px,color:#fff + classDef storage fill:#0f172a,stroke:#fbbf24,stroke-width:2px,color:#fff + classDef viz fill:#0f172a,stroke:#22d3ee,stroke-width:2px,color:#fff + + class SIM simulator + class EMQX,MOSQ,BUNKER broker + class ORION,STELLIO,FROST context + class OR,KC iot + class INFLUX,PROM,GEO storage + class GRAF,MAP,ORUI viz +``` + +--- + +## Description des flux + +### 1. **Génération des données (Simulator)** +- **Smart City Simulator** (Python) génère des données pour 10 capteurs (Traffic, Air Quality, Parking, Noise, Weather, Light) +- Intervalle de publication : 10 secondes +- Protocoles : MQTT + REST API + +### 2. **Ingestion MQTT (Brokers)** +- **EMQX** (port 11883) : Broker public, reçoit tous les capteurs +- **Mosquitto** (port 1883) : Via Traefik, accès externe +- **BunkerM** (port 1900) : MQTTS (TLS), accès sécurisé + +### 3. **Context Brokers (NGSI-LD & SensorThings)** +- **Orion-LD** : Reçoit les données au format NGSI-LD + - 10 entités (TrafficFlowObserved, AirQualityObserved, etc.) + - Smart Data Models utilisés +- **Stellio** : Alternative NGSI-LD + - 14 payloads entités + - Contexte : `https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld` +- **FROST-Server** : SensorThings API + - 21 256+ observations + - PostgreSQL + TimescaleDB + +### 4. **Plateforme IoT (OpenRemote)** +- **OpenRemote Manager** (realm `smartcity`) + - 33 assets IoT configurés + - Carte Martinique (mapsettings.json) +- **Keycloak** : Authentification OpenID Connect + - Client `openremote` avec Service Account + - Token endpoint : `/auth/realms/smartcity/protocol/openid-connect/token` + +### 5. **Stockage & Métriques** +- **InfluxDB** : Stockage temporel pour Grafana + - Bucket : `iot_data` + - Datasource dans Grafana +- **Prometheus** : Collecte des métriques + - MQTT brokers, Context brokers, OpenRemote +- **GeoServer** : Données géospatiales + - PostGIS pour centralisation + - WMS/WFS pour MapStore + +### 6. **Visualisation & Analyse** +- **Grafana** (port 3001) + - Dashboard : `smartcity-martinique-2026` + - Datasources : InfluxDB, FROST, Orion-LD +- **MapStore** : Cartographie + - Sources WMS/WFS depuis GeoServer +- **OpenRemote UI** : Manager Interface + - Visualisation des assets realm Smart City + +--- + +## Technologies clés + +| Composant | Technologie | Port | Statut | +|-----------|-------------|------|--------| +| Simulator | Python + paho-mqtt | Interne | ✅ Actif | +| EMQX | MQTT Broker | 11883 | ✅ Connecté | +| Orion-LD | NGSI-LD Broker | 1026 | ⚠️ À vérifier | +| Stellio | NGSI-LD Broker | 8080 | ⚠️ À vérifier | +| FROST-Server | SensorThings API | 8080 | ⚠️ À vérifier | +| OpenRemote | IoT Platform | 8080 | ⚠️ 403 (Service Account) | +| InfluxDB | Time Series DB | 8086 | ✅ Configuré | +| Grafana | Visualization | 3001 | ✅ Dashboard créé | +| GeoServer | GeoServer | 8080 | ⚠️ À intégrer | +| Prometheus | Metrics | 9090 | ✅ En cours | + +--- + +## Fichiers associés + +- **Simulator** : `~/smart-city-digital-twin-martinique/simulator.py` +- **Dashboard Grafana** : `~/smart-city-digital-twin-martinique/grafana_dashboard_smartcity.json` +- **Ce diagramme** : `~/smart-city-digital-twin-martinique/data-flow-diagram.md` +- **Session Resume** : `~/smart-city-digital-twin-martinique/session_resume_2026-05-04.md` + +--- + +**Dernière mise à jour :** 04 Mai 2026 +**Projet :** Smart City Digital Twin Martinique +**URL Grafana :** http://localhost:3001/d/smartcity-martinique-2026 diff --git a/data-flow-diagram.pdf b/data-flow-diagram.pdf new file mode 100644 index 0000000000000000000000000000000000000000..85d350ccfa0d7ed6eaacb852622ba813832c964e GIT binary patch literal 22962 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