Files
web-app-python/MQTT_ARCHITECTURE.md
2025-10-20 19:10:08 +02:00

5.2 KiB

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

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

{
  "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):

{
  "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):

{
  "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:

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

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

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

cd /home/alex/devel/web-app-python
source .venv/bin/activate
python scripts/test_mqtt_improved.py

2. Monitor MQTT (subscriber)

# 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

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

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

docker-compose logs -f mosquitto

Log Backend MQTT

# Filtro solo log MQTT
grep "MQTT" logs/app.log | tail -50

Statistiche Broker

# Connetti e visualizza statistiche
mosquitto_sub -h localhost -t '$SYS/#' -v