app backend prima

This commit is contained in:
2025-10-20 19:10:08 +02:00
commit 438255d27b
42 changed files with 4622 additions and 0 deletions

191
scripts/init_db.py Normal file
View File

@@ -0,0 +1,191 @@
"""
Script per inizializzare il database con dati di esempio
"""
import sys
import os
# 1. Ottieni il percorso assoluto della directory corrente dello script
current_dir = os.path.dirname(os.path.abspath(__file__))
# 2. Risali di un livello per raggiungere la directory radice (quella che contiene 'app' e 'scripts')
# Esempio: da /percorso/al/progetto/scripts a /percorso/al/progetto
project_root = os.path.join(current_dir, '..')
# 3. Aggiungi la directory radice al path di ricerca dei moduli di Python
sys.path.append(project_root)
# 4. Carica variabili d'ambiente dal file .env
from dotenv import load_dotenv
env_path = os.path.join(project_root, '.env')
load_dotenv(env_path)
from datetime import datetime, timezone
from app.core.database import SessionLocal, engine, Base
from app.models import Cliente, Sito, Utente, TipoSito, RuoloUtente
from app.core.security import get_password_hash
def init_database():
"""Crea le tabelle e inserisce dati di esempio"""
# Crea tutte le tabelle
print("Creazione tabelle...")
Base.metadata.create_all(bind=engine)
print("✓ Tabelle create")
db = SessionLocal()
try:
# Verifica se esistono già dati
existing_cliente = db.query(Cliente).first()
if existing_cliente:
print("⚠ Database già inizializzato. Skip.")
return
# 1. Crea cliente di esempio
print("\nCreazione cliente di esempio...")
cliente = Cliente(
nome="Azienda Monitoraggio SRL",
ragione_sociale="Azienda Monitoraggio SRL",
partita_iva="12345678901",
email="info@aziendamonitoraggio.it",
telefono="+39 02 1234567",
indirizzo="Via Roma 1, 20100 Milano",
attivo=True,
)
db.add(cliente)
db.flush()
print(f"✓ Cliente creato: {cliente.nome} (ID: {cliente.id})")
# 2. Crea siti di esempio
print("\nCreazione siti monitorati...")
siti = [
Sito(
cliente_id=cliente.id,
nome="Ponte Morandi",
tipo=TipoSito.PONTE,
descrizione="Ponte autostradale sulla A10",
latitudine=44.4268,
longitudine=8.9137,
comune="Genova",
provincia="GE",
regione="Liguria",
codice_identificativo="PON-001",
),
Sito(
cliente_id=cliente.id,
nome="Galleria San Boldo",
tipo=TipoSito.GALLERIA,
descrizione="Galleria stradale sul passo San Boldo",
latitudine=45.9811,
longitudine=12.1064,
comune="Cison di Valmarino",
provincia="TV",
regione="Veneto",
codice_identificativo="GAL-002",
),
Sito(
cliente_id=cliente.id,
nome="Diga del Vajont",
tipo=TipoSito.DIGA,
descrizione="Diga sul torrente Vajont",
latitudine=46.2691,
longitudine=12.3281,
comune="Erto e Casso",
provincia="PN",
regione="Friuli-Venezia Giulia",
codice_identificativo="DIG-003",
),
Sito(
cliente_id=cliente.id,
nome="Versante Cà di Sotto",
tipo=TipoSito.FRANA,
descrizione="Area soggetta a movimento franoso",
latitudine=44.3521,
longitudine=10.8464,
comune="Corniglio",
provincia="PR",
regione="Emilia-Romagna",
codice_identificativo="FRA-004",
),
]
for sito in siti:
db.add(sito)
print(f"✓ Sito creato: {sito.nome} ({sito.tipo})")
db.flush()
# 3. Crea utenti di esempio
print("\nCreazione utenti...")
utenti = [
Utente(
cliente_id=cliente.id,
email="admin@azienda.it",
password_hash=get_password_hash("admin123"),
nome="Mario",
cognome="Rossi",
telefono="+39 333 1234567",
ruolo=RuoloUtente.ADMIN,
attivo=True,
email_verificata=True,
),
Utente(
cliente_id=cliente.id,
email="operatore@azienda.it",
password_hash=get_password_hash("operatore123"),
nome="Luca",
cognome="Bianchi",
telefono="+39 333 7654321",
ruolo=RuoloUtente.OPERATORE,
attivo=True,
email_verificata=True,
),
Utente(
cliente_id=cliente.id,
email="viewer@azienda.it",
password_hash=get_password_hash("viewer123"),
nome="Anna",
cognome="Verdi",
telefono="+39 333 9876543",
ruolo=RuoloUtente.VISUALIZZATORE,
attivo=True,
email_verificata=True,
),
]
for utente in utenti:
db.add(utente)
print(f"✓ Utente creato: {utente.email} ({utente.ruolo})")
# Commit finale
db.commit()
print("\n" + "=" * 60)
print("✓ Database inizializzato con successo!")
print("=" * 60)
print("\nCredenziali di accesso:")
print("-" * 60)
for utente in utenti:
pwd = "admin123" if utente.ruolo == RuoloUtente.ADMIN else \
"operatore123" if utente.ruolo == RuoloUtente.OPERATORE else "viewer123"
print(f"Email: {utente.email:25} | Password: {pwd:15} | Ruolo: {utente.ruolo}")
print("-" * 60)
print(f"\nSiti monitorati creati: {len(siti)}")
for i, sito in enumerate(siti, 1):
print(f" {i}. {sito.nome} (ID: {sito.id}) - {sito.tipo}")
print()
except Exception as e:
print(f"\n✗ Errore durante l'inizializzazione: {e}")
db.rollback()
raise
finally:
db.close()
if __name__ == "__main__":
print("=" * 60)
print("INIZIALIZZAZIONE DATABASE - Terrain Monitor")
print("=" * 60)
init_database()

View File

@@ -0,0 +1,121 @@
"""
Script per testare l'invio di un allarme via MQTT con nuova struttura topic
Topic pattern: terrain/{cliente_id}/{sito_id}/alarms
Questo script usa la nuova architettura MQTT migliorata dove:
- cliente_id e sito_id sono nel topic (non nel payload)
- Supporto per diversi tipi di messaggi (alarms, telemetry, status)
- QoS 1 per garantire delivery
"""
import json
import time
from datetime import datetime, timezone
import paho.mqtt.client as mqtt
# Configurazione (modifica secondo il tuo setup)
MQTT_BROKER = "94.177.199.207"
MQTT_PORT = 1883
# ID dal database (verifica con: SELECT id, cliente_id, nome FROM siti;)
CLIENTE_ID = 1 # Cliente ID del sito
SITO_ID = 1 # ID del sito "Ponte Morandi"
# Topic con nuova struttura: terrain/{cliente_id}/{sito_id}/alarms
MQTT_TOPIC = f"terrain/{CLIENTE_ID}/{SITO_ID}/alarms"
# Allarme di test (sito_id e cliente_id vengono estratti dal topic)
alarm_data = {
"tipo": "movimento_terreno",
"severita": "critical", # critical, warning, info
"titolo": "🚨 TEST: Movimento terreno critico",
"descrizione": "Allarme di test per verificare notifiche push - Sistema funzionante!",
"messaggio": "Rilevato movimento anomalo superiore alla soglia di sicurezza",
"valore_rilevato": 25.5,
"valore_soglia": 10.0,
"unita_misura": "mm",
"timestamp": datetime.now(timezone.utc).isoformat(),
"dati_sensori": {
"sensore_inclinometro_1": 25.5,
"sensore_inclinometro_2": 18.3,
"temperatura": 15.5,
"umidita": 45.0
}
}
def on_connect(client, userdata, flags, rc):
"""Callback quando il client si connette"""
if rc == 0:
print("✓ Connesso al broker MQTT")
else:
print(f"✗ Connessione fallita con codice: {rc}")
def on_publish(client, userdata, mid):
"""Callback quando il messaggio viene pubblicato"""
print(f"✓ Messaggio pubblicato (message_id: {mid})")
def send_test_alarm():
"""Invia un allarme di test"""
print("=" * 70)
print("TEST INVIO ALLARME VIA MQTT - NUOVA ARCHITETTURA")
print("=" * 70)
# Crea client MQTT
client = mqtt.Client(client_id="test_alarm_sender_v2")
client.on_connect = on_connect
client.on_publish = on_publish
try:
# Connetti al broker
print(f"\nConnessione a {MQTT_BROKER}:{MQTT_PORT}...")
client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
# Start loop
client.loop_start()
time.sleep(1) # Aspetta la connessione
# Pubblica l'allarme
print(f"\nInvio allarme:")
print(f" Topic: {MQTT_TOPIC}")
print(f" Cliente ID: {CLIENTE_ID}")
print(f" Sito ID: {SITO_ID}")
print("\nPayload:")
print(json.dumps(alarm_data, indent=2, ensure_ascii=False))
print()
result = client.publish(
MQTT_TOPIC,
json.dumps(alarm_data),
qos=1 # QoS 1 per garantire delivery
)
# Aspetta che il messaggio sia pubblicato
result.wait_for_publish()
print("\n✓ Allarme inviato con successo!")
print("\nControlla:")
print(" 1. I log del backend per vedere se è stato ricevuto")
print(" 2. Il database per verificare che l'allarme sia stato salvato")
print(" 3. L'app mobile per verificare la ricezione della notifica push")
print("\nComandi utili:")
print(" - Logs backend: tail -f logs/app.log")
print(" - DB query: SELECT * FROM allarmi ORDER BY created_at DESC LIMIT 5;")
# Cleanup
time.sleep(1)
client.loop_stop()
client.disconnect()
except Exception as e:
print(f"\n✗ Errore: {e}")
client.loop_stop()
raise
print("\n" + "=" * 70)
if __name__ == "__main__":
send_test_alarm()