# Architettura MQTT - Sistema di Monitoraggio Terreni ## 📡 Struttura Topic La nuova architettura usa una struttura gerarchica dei topic MQTT per garantire scalabilità e multi-tenancy: ``` terrain/{cliente_id}/{sito_id}/{message_type} ``` ### Tipi di Messaggi | Topic Type | Descrizione | QoS | Frequenza | |------------|-------------|-----|-----------| | `alarms` | Allarmi critici/warning/info | 1 | On-event | | `telemetry` | Dati sensori periodici | 0 | 1-60 min | | `status` | Stato gateway/sensori | 0 | Periodico | ### Esempi ```bash # Allarme critico per il sito 17 del cliente 5 terrain/5/17/alarms # Telemetria sensori terrain/5/17/telemetry # Stato del gateway terrain/5/17/status ``` ## 📋 Formato Messaggi ### Allarmi (`/alarms`) **Topic**: `terrain/{cliente_id}/{sito_id}/alarms` **Payload** (JSON): ```json { "tipo": "movimento_terreno", "severita": "critical", "titolo": "Movimento terreno rilevato", "descrizione": "Rilevato movimento anomalo...", "valore_rilevato": 25.5, "valore_soglia": 10.0, "unita_misura": "mm", "timestamp": "2025-10-19T10:30:00Z", "dati_sensori": { "sensore_1": 25.5, "sensore_2": 18.3 } } ``` **Note**: - `sito_id` e `cliente_id` vengono estratti dal topic (non dal payload) - `severita`: `critical`, `warning`, `info` - `tipo`: `movimento_terreno`, `inclinazione`, `vibrazioni`, `cedimento`, `altro` ### Telemetria (`/telemetry`) **Topic**: `terrain/{cliente_id}/{sito_id}/telemetry` **Payload** (JSON): ```json { "timestamp": "2025-10-19T10:30:00Z", "sensori": { "inclinometro_1": { "valore": 12.5, "unita": "gradi", "stato": "ok" }, "temperatura": { "valore": 15.5, "unita": "celsius" } }, "batteria": 85, "segnale": -65 } ``` ### Status (`/status`) **Topic**: `terrain/{cliente_id}/{sito_id}/status` **Payload** (JSON): ```json { "timestamp": "2025-10-19T10:30:00Z", "gateway_online": true, "sensori_attivi": 4, "sensori_totali": 4, "ultimo_heartbeat": "2025-10-19T10:29:00Z", "errori": [] } ``` ## 🔌 Sottoscrizioni Backend Il backend si sottoscrive usando wildcards MQTT: ```python # Sottoscrivi a tutti gli allarmi client.subscribe("terrain/+/+/alarms", qos=1) # Sottoscrivi a tutta la telemetria client.subscribe("terrain/+/+/telemetry", qos=0) # Sottoscrivi a tutti i messaggi di status client.subscribe("terrain/+/+/status", qos=0) ``` **Wildcards**: - `+` : single-level wildcard (un livello) - `#` : multi-level wildcard (tutti i livelli rimanenti) ## 🔒 Sicurezza ### Development - Autenticazione: Anonymous (allow_anonymous = true) - Encryption: Nessuna ### Production (TODO) ```conf # mosquitto.conf allow_anonymous false password_file /mosquitto/config/passwd # TLS/SSL listener 8883 cafile /mosquitto/certs/ca.crt certfile /mosquitto/certs/server.crt keyfile /mosquitto/certs/server.key ``` ## 💾 Persistenza Mosquitto è configurato con persistenza su disco: ```conf persistence true persistence_location /mosquitto/data/ autosave_interval 300 # Salva ogni 5 minuti ``` **Vantaggi**: - Messaggi QoS > 0 non persi in caso di restart - Sottoscrizioni persistenti - Retained messages salvati ## 🧪 Test ### 1. Invia allarme di test ```bash cd /home/alex/devel/web-app-python source .venv/bin/activate python scripts/test_mqtt_improved.py ``` ### 2. Monitor MQTT (subscriber) ```bash # Installa mosquitto-clients sudo apt-get install mosquitto-clients # Sottoscrivi a tutti gli allarmi mosquitto_sub -h localhost -t "terrain/+/+/alarms" -v # Sottoscrivi a tutti i messaggi mosquitto_sub -h localhost -t "terrain/#" -v ``` ### 3. Pubblica messaggio manuale ```bash # Allarme critico mosquitto_pub -h localhost \ -t "terrain/5/17/alarms" \ -m '{"tipo":"movimento_terreno","severita":"critical","titolo":"Test","timestamp":"2025-10-19T10:30:00Z"}' \ -q 1 ``` ## 📊 Helper Python Usa l'helper `MQTTTopics` per costruire topic standardizzati: ```python from app.mqtt.topics import MQTTTopics # Costruisci topic topic = MQTTTopics.build_topic( cliente_id=5, sito_id=17, topic_type="alarms" ) # Output: "terrain/5/17/alarms" # Parse topic info = MQTTTopics.parse_topic("terrain/5/17/alarms") # Output: {'cliente_id': 5, 'sito_id': 17, 'topic_type': 'alarms'} # Pattern sottoscrizione pattern = MQTTTopics.get_subscription_pattern("alarms") # Output: "terrain/+/+/alarms" ``` ## 🚀 Migrazione dal Vecchio Sistema ### Prima (vecchio) ``` Topic: terrain/alarms/1 Payload: {"sito_id": 17, "tipo": "...", ...} ``` ### Dopo (nuovo) ``` Topic: terrain/5/17/alarms Payload: {"tipo": "...", ...} # sito_id estratto dal topic ``` ### Retrocompatibilità Il sistema continua a funzionare con il vecchio formato, ma è consigliato migrare ai nuovi topic per: - ✅ Migliore separazione multi-tenant - ✅ Filtraggio per cliente - ✅ Scalabilità - ✅ Standard IoT ## 📈 Performance - **Max throughput**: ~10,000 msg/sec (con QoS 0) - **Latenza**: < 10ms (LAN) - **Retained messages**: 1000 max - **Connections**: Illimitate (configurabile) ## 🔍 Monitoraggio ### Log Mosquitto ```bash docker-compose logs -f mosquitto ``` ### Log Backend MQTT ```bash # Filtro solo log MQTT grep "MQTT" logs/app.log | tail -50 ``` ### Statistiche Broker ```bash # Connetti e visualizza statistiche mosquitto_sub -h localhost -t '$SYS/#' -v ```