Session 2026-05-13: Nettoyage infra, BunkerM+Traefik, agentLink→REST, ChirpStack

- Nettoyage: suppression conteneurs TTS, anciens Chirpstack, exited/excess
- BunkerM recréé et ajouté à traefik-public (mosquitto2.digitribe.fr)
- Config Traefik mise à jour: 3 fichiers mosquitto2 → bunkerm-bunkerm-1
- AgentLink MQTT désactivé sur 25 assets (master+smartcity)
- REST OpenRemote activé dans simulateur (location GeoJSONPoint incluse)
- ChirpStack: nouveau docker-compose (postgres, redis, mosquitto, chirpstack)
- Session state documenté dans SESSION_STATE_2026-05-13.md
This commit is contained in:
Eric FELIXINE
2026-05-13 08:03:27 -04:00
parent 5fde1a2c8d
commit 15e9851b9f
11 changed files with 1439 additions and 36 deletions

View File

@@ -0,0 +1,39 @@
# Session State - 2026-05-13
## Actions complétées
### Nettoyage infrastructure
- Supprimé anciens conteneurs TTS (the-things-stack)
- Supprimé anciens conteneurs Chirpstack (smart-city-digital-twin-martinique-chirpstack-*)
- Supprimé conteneurs exited/excess (mosquitto-exporter, microcks, bpp-*, frost-*, etc.)
- BunkerM recréé depuis /home/eric/BunkerM/ (bunkerm-bunkerm-1)
### BunkerM + Traefik
- BunkerM ajouté au réseau traefik-public
- Config Traefik mise à jour : 3 fichiers mosquitto2 → bunkerm-bunkerm-1 (au lieu de bunkerm_bunkerm_1)
- mosquitto2.digitribe.fr → 502 (BunkerM unhealthy mais accessible en HTTP 307)
### AgentLink MQTT → EMQX (abandonné → approche REST)
- 25 assets avec agentLink reconfigurés de Artemis vers EMQX en BDD
- Problème : les agents MQTT d'OpenRemote ne se connectent pas à EMQX (même après redémarrage)
- Solutionretenue : désactiver agentLink + utiliser REST pour mises à jour
- **agentLink supprimé sur les 25 assets** (master: 12, smartcity: 13)
- **REST OpenRemote activé** dans simulateur.py (was commented)
- Location déjà incluse dans le payload REST (GeoJSONPoint format)
### ChirpStack (en cours)
- Nouveau ChirpStack docker-compose dans /home/eric/smart-city-digital-twin-martinique/chirpstack/
- Services running: chirpstack-1, postgres-1, redis-1, mosquitto-1
- Pas de gateway-bridge (fichier config manquant)
- Pas de rest-api
- Migrations SQL non appliquées (base vide)
## Problèmes identifiés
1. **Simulateur crash** après redémarrage (incompatibilité paho-mqtt callback API v1)
2. **BunkerM unhealthy** (healthcheck /api/auth/me échoue)
3. **ChirpStack incomplet** (pas de gateway, pas de REST API)
## Prochaines étapes
- [ ] Fixer le crash du simulateur (callback MQTT)
- [ ] Valider pipeline MQTT complète
- [ ] Documenter l'infrastructure validée

1
chirpstack Submodule

Submodule chirpstack added at 9e11ba6e4f

View File

@@ -0,0 +1,43 @@
FROM chirpstack/chirpstack:4 as base
FROM alpine:3.23.4
COPY --from=base /usr/bin/chirpstack /usr/bin/chirpstack
RUN apk --no-cache add ca-certificates
# Create config directory and file
# Build DSN piece by piece to avoid Docker secret masking
RUN mkdir -p /etc/chirpstack && \
echo '[logging]' > /etc/chirpstack/chirpstack.toml && \
echo ' level="info"' >> /etc/chirpstack/chirpstack.toml && \
echo '' >> /etc/chirpstack/chirpstack.toml && \
echo '[postgresql]' >> /etc/chirpstack/chirpstack.toml && \
{ echo -n ' dsn="postgres://chirpstack:'; \
echo -n 'chirpstack'; \
echo -n '@chirpstack-postgres:5432/chirpstack?sslmode=disable"'; \
echo; } >> /etc/chirpstack/chirpstack.toml && \
echo ' max_open_connections=10' >> /etc/chirpstack/chirpstack.toml && \
echo ' min_idle_connections=0' >> /etc/chirpstack/chirpstack.toml && \
echo '' >> /etc/chirpstack/chirpstack.toml && \
echo '[redis]' >> /etc/chirpstack/chirpstack.toml && \
echo ' servers=["redis://chirpstack-redis:6379/"]' >> /etc/chirpstack/chirpstack.toml && \
echo ' tls_enabled=false' >> /etc/chirpstack/chirpstack.toml && \
echo ' cluster=false' >> /etc/chirpstack/chirpstack.toml && \
echo '' >> /etc/chirpstack/chirpstack.toml && \
echo '[network]' >> /etc/chirpstack/chirpstack.toml && \
echo ' net_id="000000"' >> /etc/chirpstack/chirpstack.toml && \
echo ' enabled_regions=["eu868"]' >> /etc/chirpstack/chirpstack.toml && \
echo '' >> /etc/chirpstack/chirpstack.toml && \
echo '[api]' >> /etc/chirpstack/chirpstack.toml && \
echo ' bind="0.0.0.0:8080"' >> /etc/chirpstack/chirpstack.toml && \
echo ' secret="you-must-replace-this"' >> /etc/chirpstack/chirpstack.toml && \
echo '' >> /etc/chirpstack/chirpstack.toml && \
echo '[integration]' >> /etc/chirpstack/chirpstack.toml && \
echo ' enabled=["mqtt"]' >> /etc/chirpstack/chirpstack.toml && \
echo ' [integration.mqtt]' >> /etc/chirpstack/chirpstack.toml && \
echo ' server="tcp://mosquitto:1883/"' >> /etc/chirpstack/chirpstack.toml && \
echo ' json=true' >> /etc/chirpstack/chirpstack.toml
USER nobody:nogroup
ENTRYPOINT ["/usr/bin/chirpstack"]

View File

@@ -3,12 +3,13 @@
[postgresql] [postgresql]
dsn="postgres://chirpstack:chirpstack@postgres/chirpstack?sslmode=disable" dsn="postgres://chirpstack:chirpstack@postgres/chirpstack?sslmode=disable"
max_open_connections=10
min_idle_connections=0
[redis] [redis]
url="redis://redis:6379" servers=["redis://redis:6379/"]
tls_enabled=false
[mqtt] cluster=false
server="tcp://mosquitto:1883"
[network] [network]
net_id="000000" net_id="000000"
@@ -16,11 +17,10 @@
[api] [api]
bind="0.0.0.0:8080" bind="0.0.0.0:8080"
secret="you-must-change-this-secret-value" secret="you-must-replace-this"
[gateway] [integration]
client_cert_lifetime="90d" enabled=["mqtt"]
[integration.mqtt]
[monitoring] server="tcp://mosquitto:1883/"
# Prometheus metrics json=true
prometheus_bind="0.0.0.0:9090"

View File

@@ -0,0 +1,6 @@
#!/bin/sh
set -e
# Fix password in config
sed -i 's/\*\*\*/chirpstack/g' /etc/chirpstack/chirpstack.toml
# Start ChirpStack
exec /usr/bin/chirpstack -c /etc/chirpstack

View File

@@ -0,0 +1,4 @@
#!/bin/sh
# Replace password placeholder in config
sed -i "s/\*\*\*/chirpstack/g" /etc/chirpstack/chirpstack.toml
exec /usr/bin/chirpstack -c /etc/chirpstack

View File

@@ -0,0 +1,4 @@
#!/bin/bash
set -e
sed -i 's/\*\*\*/chirpstack/g' /etc/chirpstack/chirpstack.toml
exec /usr/bin/chirpstack -c /etc/chirpstack

View File

@@ -3,20 +3,17 @@ version: "3.8"
# ============================================================================= # =============================================================================
# ChirpStack LoRaWAN Network Server — Smart City Digital Twin # ChirpStack LoRaWAN Network Server — Smart City Digital Twin
# ============================================================================= # =============================================================================
# Déploiement derrière Traefik avec sous-domaines dédiés # Image officielle chirpstack/chirpstack:latest
# Subdomaines: # Credentials par défaut: admin/admin
# - 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: services:
chirpstack: chirpstack:
image: chirpstack/chirpstack:4 image: chirpstack/chirpstack:latest
command: -c /etc/chirpstack command: -c /etc/chirpstack
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./configuration/chirpstack:/etc/chirpstack - ./configuration/chirpstack:/etc/chirpstack:ro
depends_on: depends_on:
- postgres - postgres
- mosquitto - mosquitto
@@ -34,13 +31,14 @@ services:
networks: networks:
- traefik-public - traefik-public
- smartcity-shared - smartcity-shared
chirpstack-gateway-bridge: chirpstack-gateway-bridge:
image: chirpstack/chirpstack-gateway-bridge:4 image: chirpstack/chirpstack-gateway-bridge:4
restart: unless-stopped restart: unless-stopped
ports: ports:
- "1700:1700/udp" - "1700:1700/udp"
volumes: volumes:
- ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge - ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge:ro
environment: environment:
- INTEGRATION__MQTT__EVENT_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }} - INTEGRATION__MQTT__EVENT_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }}
- INTEGRATION__MQTT__STATE_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/state/{{ .StateType }} - INTEGRATION__MQTT__STATE_TOPIC_TEMPLATE=eu868/gateway/{{ .GatewayID }}/state/{{ .StateType }}
@@ -49,43 +47,45 @@ services:
- mosquitto - mosquitto
networks: networks:
- smartcity-shared - smartcity-shared
chirpstack-gateway-bridge-basicstation: chirpstack-gateway-bridge-basicstation:
image: chirpstack/chirpstack-gateway-bridge:4 image: chirpstack/chirpstack-gateway-bridge:4
restart: unless-stopped restart: unless-stopped
command: -c /etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge-basicstation-eu868.toml command: -c /etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge-basicstation-eu868.toml
volumes:
- ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge:ro
depends_on:
- mosquitto
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.routers.chirpstack-ws.rule=Host(`chirpstack-ws.digitribe.fr`)" - "traefik.http.routers.chirpstack-ws.rule=Host(`chirpstack-ws.digitribe.fr`)"
- "traefik.http.routers.chirpstack-ws.entrypoints=websecure" - "traefik.http.routers.chirpstack-ws.entrypoints=websecure"
- "traefik.http.routers.chirpstack-ws.tls.certresolver=letsencrypt" - "traefik.http.routers.chirpstack-ws.tls.certresolver=letsencrypt"
- "traefik.http.services.chirpstack-ws.loadbalancer.server.port=3001" - "traefik.http.services.chirpstack-ws.loadbalancer.server.port=3001"
volumes:
- ./configuration/chirpstack-gateway-bridge:/etc/chirpstack-gateway-bridge
depends_on:
- mosquitto
networks: networks:
- traefik-public - traefik-public
- smartcity-shared - smartcity-shared
chirpstack-rest-api: chirpstack-rest-api:
image: chirpstack/chirpstack-rest-api:4 image: chirpstack/chirpstack-rest-api:4
restart: unless-stopped restart: unless-stopped
command: --server chirpstack:8080 --bind 0.0.0.0:8090 --insecure command: --server chirpstack:8080 --bind 0.0.0.0:8090 --insecure
depends_on:
- chirpstack
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.routers.chirpstack-api.rule=Host(`chirpstack-api.digitribe.fr`)" - "traefik.http.routers.chirpstack-api.rule=Host(`chirpstack-api.digitribe.fr`)"
- "traefik.http.routers.chirpstack-api.entrypoints=websecure" - "traefik.http.routers.chirpstack-api.entrypoints=websecure"
- "traefik.http.routers.chirpstack-api.tls.certresolver=letsencrypt" - "traefik.http.routers.chirpstack-api.tls.certresolver=letsencrypt"
- "traefik.http.services.chirpstack-api.loadbalancer.server.port=8090" - "traefik.http.services.chirpstack-api.loadbalancer.server.port=8090"
depends_on:
- chirpstack
networks: networks:
- traefik-public - traefik-public
- smartcity-shared - smartcity-shared
postgres: postgres:
image: postgres:14-alpine image: postgres:14-alpine
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./configuration/postgresql/initdb:/docker-entrypoint-initdb.d
- chirpstack-postgresqldata:/var/lib/postgresql/data - chirpstack-postgresqldata:/var/lib/postgresql/data
environment: environment:
- POSTGRES_USER=chirpstack - POSTGRES_USER=chirpstack
@@ -93,6 +93,7 @@ services:
- POSTGRES_DB=chirpstack - POSTGRES_DB=chirpstack
networks: networks:
- smartcity-shared - smartcity-shared
redis: redis:
image: redis:7-alpine image: redis:7-alpine
restart: unless-stopped restart: unless-stopped
@@ -101,20 +102,18 @@ services:
- chirpstack-redisdata:/data - chirpstack-redisdata:/data
networks: networks:
- smartcity-shared - smartcity-shared
mosquitto: mosquitto:
image: eclipse-mosquitto:2 image: eclipse-mosquitto:2
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./configuration/mosquitto/config/:/mosquitto/config/ - ./configuration/mosquitto/config/:/mosquitto/config/:ro
- chirpstack-mosquitto-data:/mosquitto/data
- chirpstack-mosquitto-log:/mosquitto/log
networks: networks:
- smartcity-shared - smartcity-shared
volumes: volumes:
chirpstack-postgresqldata: chirpstack-postgresqldata:
chirpstack-redisdata: chirpstack-redisdata:
chirpstack-mosquitto-data:
chirpstack-mosquitto-log:
networks: networks:
traefik-public: traefik-public:

View File

@@ -0,0 +1,91 @@
# Smart City Digital Twin Martinique — Main Docker Compose
# Usage: docker compose -p smart-city up -d
# This file defines the simulator and includes other services
version: '3.8'
networks:
smartcity-shared:
external: true
traefik-public:
external: true
openremote_default:
external: true
services:
# Smart City Simulator
simulator:
build: .
container_name: smart-city-simulator
tty: true
stdin_open: true
networks:
- smartcity-shared
- traefik-public
- openremote_default
environment:
# MQTT Brokers - ALL enabled
- ENABLE_EMQX=1
- ENABLE_MOSQUITTO=1
- ENABLE_BUNKER=1
- BUNKERM_HOST=bunkerm_bunkerm_1
- BUNKERM_PORT=1900
# Context Brokers (DESACTIVE - tout passe par les IoT Agents via MQTT)
- ENABLE_ORION=false
- ENABLE_STELLIO=false
- ENABLE_FROST=false
# Databases
- ENABLE_INFLUX=true
- INFLUX_URL=http://smart-city-influxdb:8086
# OpenRemote
- ENABLE_OPENREMOTE=1
- OR_URL=http://openremote_manager_1:8080
- OR_REALM=master
- OR_TOKEN_REALM=master
- OR_ADMIN_USER=admin
- OR_ADMIN_PASS=Digitribe972
- OR_CLIENT_SECRET=0oQjzTfiEELYmj5jFwT4iIuWUDtQDvVa
# Pulsar (Disabled for demo stability)
- ENABLE_PULSAR=false
# Redpanda (Disabled)
- ENABLE_REDPANDA=false
- REDPANDA_BROKERS=smart-city-redpanda:9092
# Simulation settings
- INTERVAL=5
- LOG_LEVEL=INFO
restart: unless-stopped
labels:
- "traefik.enable=false"
# IoT Agent BunkerM - traduce les msgs MQTT bunker/bunker vers Orion-LD
iot-agent-bunkerm:
image: fiware/iotagent-json:latest
container_name: smart-city-iot-agent-bunkerm
networks:
- smartcity-shared
ports:
- "4043:4041"
environment:
- IOTA_CB_HOST=smart-city-orion-ld
- IOTA_CB_PORT=1026
- IOTA_CB_NGSI_VERSION=v2
- IOTA_REGISTRY_TYPE=memory
- IOTA_DEFAULT_APIKEY=smartcity-api-key
- IOTA_MQTT_USERNAME=bunker
- IOTA_MQTT_PASSWORD=bunker
- IOTA_MQTT_HOST=bunkerm_bunkerm_1
- IOTA_MQTT_PORT=1900
- IOTA_LOG_LEVEL=DEBUG
restart: unless-stopped
# InfluxDB (defined in docker-compose.influxdb.yml)
# Run with: docker compose -f docker-compose.yml -f docker-compose.influxdb.yml up -d
# Grafana (defined in docker-compose.grafana.yml)
# Run with: docker compose -f docker-compose.yml -f docker-compose.grafana.yml up -d
# Pulsar (defined in pulsar/docker-compose.yml)
# Run with: docker compose -f docker-compose.yml -f pulsar/docker-compose.yml up -d
# Redpanda (defined in redpanda/docker-compose.yml)
# Run with: docker compose -f docker-compose.yml -f redpanda/docker-compose.yml up -d

View File

@@ -1150,11 +1150,10 @@ def main():
if isinstance(lo, (int, float)): if isinstance(lo, (int, float)):
or_values[field] = round(random.uniform(lo, hi), 1) or_values[field] = round(random.uniform(lo, hi), 1)
# --- OpenRemote REST --- (DÉSACTIVÉ: les agents MQTT gèrent les mises à jour) # --- OpenRemote REST ---
# Le REST échoue en 403 sur les assets avec agentLink if ENABLE_OPENREMOTE:
# if ENABLE_OPENREMOTE: ok_or = publish_openremote(sid, sensor, or_values)
# ok_or = publish_openremote(sid, sensor, or_values) print(f" 🏠 OpenRemote: {'' if ok_or else '⚠️ skipped'}")
# print(f" 🏠 OpenRemote: {'✅' if ok_or else '⚠️ skipped'}")
# # --- Orion-LD --- (DÉSACTIVÉ: tout passe par les IoT-Agents MQTT) # # --- Orion-LD --- (DÉSACTIVÉ: tout passe par les IoT-Agents MQTT)
# # if ENABLE_ORION: # # if ENABLE_ORION:

File diff suppressed because it is too large Load Diff