diff --git a/DOCKER-ARCHITECTURE-2026-05-07.md b/DOCKER-ARCHITECTURE-2026-05-07.md index 4fbf1b2e..6fdb3182 100644 --- a/DOCKER-ARCHITECTURE-2026-05-07.md +++ b/DOCKER-ARCHITECTURE-2026-05-07.md @@ -1,12 +1,12 @@ -# Smart City Digital Twin - Architecture Docker (Stellio Pipeline Added) -**Date** : 07 mai 2026 +# Smart City Digital Twin - Architecture Docker (LoRaWAN Added) +**Date** : 12 mai 2026 **Projet** : `smart-city-digital-twin-martinique` **Auteur** : Éric FELIXINE (via Hermes Agent) --- ## 1. Vue d'ensemble -Cette cartographie présente l'architecture Docker complète du jumeau numérique Smart City (Martinique), incluant les conteneurs, images, réseaux et ports exposés. +Cette cartographie présente l'architecture Docker complète du jumeau numérique Smart City (Martinique), incluant les conteneurs, images, réseaux et ports exposés. **Mise à jour 2026-05-12** : ajout de ChirpStack et The Things Stack pour la connectivité LoRaWAN. --- @@ -22,6 +22,22 @@ Simulator → MQTT Brokers (Mosquitto/EMQX/BunkerM) → IoT Agents → Orion-LD Simulator → MQTT Brokers → IoT Agents → Stellio Context Broker → QuantumLeap-Stellio → CrateDB-Stellio → Grafana ``` +### Pipeline LoRaWAN ChirpStack (Nouveau 🆕) +``` +Gateway LoRaWAN (UDP 1700) → ChirpStack Gateway Bridge → ChirpStack → MQTT (Mosquitto interne) → EMQX → IoT Agents → Orion-LD → ... +``` + +### Pipeline LoRaWAN The Things Stack (Nouveau 🆕) +``` +Gateway LoRaWAN (UDP 1700) → TTS Stack → MQTT/REST API → EMQX → IoT Agents → Orion-LD → ... +``` + +### Pipeline OpenRemote (En cours ⚠️) +``` +Simulator → REST API (PUT assets avec location) → OpenRemote Manager → Map Martinique +Simulator → MQTT (Artemis broker) → OpenRemote Agents → Asset values +``` + --- ## 3. Liste des Conteneurs Actifs (Projet Smart City) @@ -46,9 +62,20 @@ Simulator → MQTT Brokers → IoT Agents → Stellio Context Broker → Quantum | **`smart-city-cratedb-stellio`** | `crate:latest` | `smartcity-shared` | `4200:4200` | | `smart-city-redis` | `redis:7-alpine` | `smartcity-shared` | `6379:6379` | | `smart-city-grafana` | `grafana/grafana:latest` | `smartcity-shared`, `traefik-public` | `3000:3000` | -| `openremote-manager-1` | `openremote/manager:latest` | `openremote_default`, `smartcity-shared` | `8080:8080`, `8443:8443` | -| `openremote-keycloak-1` | `openremote/keycloak:latest` | `openremote_default`, `smartcity-shared` | `8080:8080`, `8443:8443` | -| `traefik` | `traefik:v3.0` | `traefik-public`, `openremote_default` | `80:80`, `443:443` | +|| `openremote-manager-1` | `openremote/manager:latest` | `openremote_default`, `smartcity-shared` | `8080:8080`, `8443:8443` | +|| `openremote-keycloak-1` | `openremote/keycloak:latest` | `openremote_default`, `smartcity-shared` | `8080:8080`, `8443:8443` | +|| `traefik` | `traefik:v3.0` | `traefik-public`, `openremote_default` | `80:80`, `443:443` | +|| **ChirpStack LoRaWAN** | | | | +|| `chirpstack-chirpstack-1` | `chirpstack/chirpstack:4` | `chirpstack-internal`, `traefik-public`, `smartcity-shared` | `8080:8080` | +|| `chirpstack-gateway-bridge-1` | `chirpstack/chirpstack-gateway-bridge:4` | `chirpstack-internal` | `1700:1700/udp` | +|| `chirpstack-rest-api-1` | `chirpstack/chirpstack-rest-api:4` | `chirpstack-internal`, `traefik-public` | `8090:8090` | +|| `chirpstack-postgres-1` | `postgres:14-alpine` | `chirpstack-internal` | `5432` | +|| `chirpstack-redis-1` | `redis:7-alpine` | `chirpstack-internal` | `6379` | +|| `chirpstack-mosquitto-1` | `eclipse-mosquitto:2` | `chirpstack-internal`, `smartcity-shared` | `1883` | +|| **The Things Stack LoRaWAN** | | | | +|| `tts-stack-1` | `thethingsnetwork/lorawan-stack:latest` | `tts-internal`, `traefik-public`, `smartcity-shared` | `1885:1885`, `1884:1884`, `1700:1700/udp` | +|| `tts-postgres-1` | `postgres:14` | `tts-internal` | `5432` | +|| `tts-redis-1` | `redis:7` | `tts-internal` | `6379` | --- @@ -58,8 +85,10 @@ Simulator → MQTT Brokers → IoT Agents → Stellio Context Broker → Quantum |---------|----------------------| | `smartcity-shared` | Tous les services Smart City (simulator, brokers, context brokers, databases, grafana) | | `stellio-context-broker_default` | Stellio services (api-gateway, subscription, search, kafka, postgres) | -| `traefik-public` | Services exposés via Traefik (grafana, mapstore, pulsar, stellio, orion, etc.) | +| `traefik-public` | Services exposés via Traefik (grafana, mapstore, pulsar, stellio, orion, chirpstack, tts, etc.) | | `openremote_default` | OpenRemote services (manager, keycloak, postgresql) | +| `chirpstack-internal` | ChirpStack services (chirpstack, gateway-bridge, rest-api, postgres, redis, mosquitto) | +| `tts-internal` | TTS services (stack, postgres, redis) | --- diff --git a/data-flow-diagram.md b/data-flow-diagram.md index efc86baf..f8b96628 100644 --- a/data-flow-diagram.md +++ b/data-flow-diagram.md @@ -1,28 +1,23 @@ -# Smart City Digital Twin - Data Flow Diagram (Updated 2026-05-06) +# Smart City Digital Twin - Data Flow Diagram (Updated 2026-05-12) -## Architecture évoluée : 1 IoT-Agent par broker MQTT +## Architecture complète avec LoRaWAN ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Smart City Simulator (Python) │ -│ Publie sur 3 brokers MQTT avec format IoT-Agent JSON │ +│ Publie sur 3 brokers MQTT + REST vers OpenRemote │ └──────────┬────────────────────┬──────────────────────┬───────────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ 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 │ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │ │ │ └───────────────────────┴──────────────────────┘ @@ -34,33 +29,150 @@ │ MongoDB backend │ └─────────┬───────────┘ │ - │ Subscription (id: 69fbb09af55b82cad2a38008) - │ Forward to QuantumLeap + │ Subscription → QuantumLeap ▼ ┌─────────────────────┐ │ QuantumLeap │ │ (port 8668) │ - │ /v2/op/notify │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ CrateDB │ │ (ports 5432/4200)│ - │ DB: quantumleap │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ Grafana │ │ (port 3001) │ - │ Datasource: │ - │ CrateDB-SmartCity│ └─────────────────────┘ + +═══════════════════════════════════════════════════════════════════════════════ + 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}` diff --git a/docker-compose.chirpstack.yml b/docker-compose.chirpstack.yml new file mode 100644 index 00000000..60433cf9 --- /dev/null +++ b/docker-compose.chirpstack.yml @@ -0,0 +1,134 @@ +version: "3.8" + +# ============================================================================= +# ChirpStack LoRaWAN Network Server — Smart City Digital Twin +# ============================================================================= +# Déploiement derrière Traefik avec sous-domaines dédiés +# Subdomaines: +# - chirpstack.digitribe.fr → Console web (port 8080) +# - chirpstack-api.digitribe.fr → REST API (port 8090) +# - chirpstack-ws.digitribe.fr → Gateway Bridge WebSocket (port 3001) +# ============================================================================= + +services: + chirpstack: + image: chirpstack/chirpstack:4 + command: -c /etc/chirpstack + restart: unless-stopped + volumes: + - ./configuration/chirpstack:/etc/chirpstack + depends_on: + - postgres + - mosquitto + - redis + environment: + - MQTT_BROKER_HOST=mosquitto + - REDIS_HOST=redis + - POSTGRESQL_HOST=postgres + labels: + - "traefik.enable=true" + - "traefik.http.routers.chirpstack.rule=Host(`chirpstack.digitribe.fr`)" + - "traefik.http.routers.chirpstack.entrypoints=websecure" + - "traefik.http.routers.chirpstack.tls.certresolver=letsencrypt" + - "traefik.http.services.chirpstack.loadbalancer.server.port=8080" + networks: + - traefik-public + - chirpstack-internal + - smartcity-shared + + chirpstack-gateway-bridge: + image: chirpstack/chirpstack-gateway-bridge:4 + restart: unless-stopped + ports: + - "1700:1700/udp" + volumes: + - ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge + environment: + - INTEGRATION__MQTT__EVENT_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }} + - INTEGRATION__MQTT__STATE_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/state/{{ .StateType }} + - INTEGRATION__MQTT__COMMAND_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/command/# + depends_on: + - mosquitto + networks: + - chirpstack-internal + + chirpstack-gateway-bridge-basicstation: + image: chirpstack/chirpstack-gateway-bridge:4 + restart: unless-stopped + command: -c /etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge-basicstation-eu868.toml + labels: + - "traefik.enable=true" + - "traefik.http.routers.chirpstack-ws.rule=Host(`chirpstack-ws.digitribe.fr`)" + - "traefik.http.routers.chirpstack-ws.entrypoints=websecure" + - "traefik.http.routers.chirpstack-ws.tls.certresolver=letsencrypt" + - "traefik.http.services.chirpstack-ws.loadbalancer.server.port=3001" + volumes: + - ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge + depends_on: + - mosquitto + networks: + - traefik-public + - chirpstack-internal + + chirpstack-rest-api: + image: chirpstack/chirpstack-rest-api:4 + restart: unless-stopped + command: --server chirpstack:8080 --bind 0.0.0.0:8090 --insecure + labels: + - "traefik.enable=true" + - "traefik.http.routers.chirpstack-api.rule=Host(`chirpstack-api.digitribe.fr`)" + - "traefik.http.routers.chirpstack-api.entrypoints=websecure" + - "traefik.http.routers.chirpstack-api.tls.certresolver=letsencrypt" + - "traefik.http.services.chirpstack-api.loadbalancer.server.port=8090" + depends_on: + - chirpstack + networks: + - traefik-public + - chirpstack-internal + + postgres: + image: postgres:14-alpine + restart: unless-stopped + volumes: + - ./configuration/postgresql/initdb:/docker-entrypoint-initdb.d + - chirpstack-postgresqldata:/var/lib/postgresql/data + environment: + - POSTGRES_USER=chirpstack + - POSTGRES_PASSWORD=chirpstack + - POSTGRES_DB=chirpstack + networks: + - chirpstack-internal + + redis: + image: redis:7-alpine + restart: unless-stopped + command: redis-server --save 300 1 --save 60 100 --appendonly no + volumes: + - chirpstack-redisdata:/data + networks: + - chirpstack-internal + + mosquitto: + image: eclipse-mosquitto:2 + restart: unless-stopped + volumes: + - ./configuration/mosquitto/config/:/mosquitto/config/ + - chirpstack-mosquitto-data:/mosquitto/data + - chirpstack-mosquitto-log:/mosquitto/log + networks: + - chirpstack-internal + - smartcity-shared + +volumes: + chirpstack-postgresqldata: + chirpstack-redisdata: + chirpstack-mosquitto-data: + chirpstack-mosquitto-log: + +networks: + traefik-public: + external: true + smartcity-shared: + external: true + chirpstack-internal: + driver: bridge diff --git a/docker-compose.the-things-stack.yml b/docker-compose.the-things-stack.yml new file mode 100644 index 00000000..c9339361 --- /dev/null +++ b/docker-compose.the-things-stack.yml @@ -0,0 +1,78 @@ +version: "3.8" + +# ============================================================================= +# The Things Stack LoRaWAN Network Server — Smart City Digital Twin +# ============================================================================= +# Déploiement derrière Traefik avec sous-domaines dédiés +# Subdomaines: +# - tts.digitribe.fr → Console web (port 1885) +# - tts-api.digitribe.fr → REST API (port 1884) +# ============================================================================= + +services: + tts-postgres: + image: postgres:14 + restart: unless-stopped + environment: + - POSTGRES_PASSWORD=root + - POSTGRES_USER=root + - POSTGRES_DB=ttn_lorawan + volumes: + - tts-postgres-data:/var/lib/postgresql/data + networks: + - tts-internal + + tts-redis: + image: redis:7 + command: redis-server --appendonly yes + restart: unless-stopped + volumes: + - tts-redis-data:/data + networks: + - tts-internal + + tts-stack: + image: thethingsnetwork/lorawan-stack:latest + entrypoint: ttn-lw-stack -c /config/ttn-lw-stack-docker.yml + command: start + restart: unless-stopped + depends_on: + - tts-redis + - tts-postgres + volumes: + - ./configuration/the-things-stack/config:/config:ro + - ./configuration/the-things-stack/blob:/srv/ttn-lorawan/public/blob + environment: + TTN_LW_BLOB_LOCAL_DIRECTORY: /srv/ttn-lorawan/public/blob + TTN_LW_REDIS_ADDRESS: tts-redis:6379 + TTN_LW_IS_DATABASE_URI: postgres://root:***@tts-postgres:5432/ttn_lorawan?sslmode=disable + ports: + - "1700:1700/udp" + labels: + - "traefik.enable=true" + # Console web + - "traefik.http.routers.tts-console.rule=Host(`tts.digitribe.fr`)" + - "traefik.http.routers.tts-console.entrypoints=websecure" + - "traefik.http.routers.tts-console.tls.certresolver=letsencrypt" + - "traefik.http.services.tts-console.loadbalancer.server.port=1885" + # API REST + - "traefik.http.routers.tts-api.rule=Host(`tts-api.digitribe.fr`)" + - "traefik.http.routers.tts-api.entrypoints=websecure" + - "traefik.http.routers.tts-api.tls.certresolver=letsencrypt" + - "traefik.http.services.tts-api.loadbalancer.server.port=1884" + networks: + - traefik-public + - tts-internal + - smartcity-shared + +volumes: + tts-postgres-data: + tts-redis-data: + +networks: + traefik-public: + external: true + smartcity-shared: + external: true + tts-internal: + driver: bridge