Improve Dashboard functionality
This commit is contained in:
@@ -98,7 +98,7 @@ def carica_rubrica():
|
|||||||
UTENTI_SIP_DMR = carica_rubrica()
|
UTENTI_SIP_DMR = carica_rubrica()
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# DASHBOARD MANAGER (Motore Dati)
|
# DASHBOARD MANAGER (Motore Dati - Modificato Sincrono)
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
class DashboardManager:
|
class DashboardManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -112,7 +112,7 @@ class DashboardManager:
|
|||||||
try: await ws.send_str(msg_str)
|
try: await ws.send_str(msg_str)
|
||||||
except Exception: self.ws_clients.discard(ws)
|
except Exception: self.ws_clients.discard(ws)
|
||||||
|
|
||||||
async def inizia_chiamata(self, id_chiamata, direzione, mittente, destinatario):
|
def inizia_chiamata(self, id_chiamata, direzione, mittente, destinatario):
|
||||||
nom_mittente = get_nominativo(mittente)
|
nom_mittente = get_nominativo(mittente)
|
||||||
nom_dest = get_nominativo(destinatario)
|
nom_dest = get_nominativo(destinatario)
|
||||||
|
|
||||||
@@ -126,20 +126,20 @@ class DashboardManager:
|
|||||||
"stato": "ON"
|
"stato": "ON"
|
||||||
}
|
}
|
||||||
self.chiamate_attive[id_chiamata] = dati
|
self.chiamate_attive[id_chiamata] = dati
|
||||||
await self.broadcast({"evento": "chiamata_iniziata", "dati": dati})
|
asyncio.create_task(self.broadcast({"evento": "chiamata_iniziata", "dati": dati}))
|
||||||
|
|
||||||
async def aggiorna_rx(self, id_chiamata):
|
def aggiorna_rx(self, id_chiamata):
|
||||||
if id_chiamata in self.chiamate_attive:
|
if id_chiamata in self.chiamate_attive:
|
||||||
self.chiamate_attive[id_chiamata]["ultimo_frame"] = time.time()
|
self.chiamate_attive[id_chiamata]["ultimo_frame"] = time.time()
|
||||||
|
|
||||||
async def termina_chiamata(self, id_chiamata):
|
def termina_chiamata(self, id_chiamata):
|
||||||
if id_chiamata in self.chiamate_attive:
|
if id_chiamata in self.chiamate_attive:
|
||||||
dati = self.chiamate_attive.pop(id_chiamata)
|
dati = self.chiamate_attive.pop(id_chiamata)
|
||||||
dati["fine"] = time.time()
|
dati["fine"] = time.time()
|
||||||
dati["durata"] = round(dati["fine"] - dati["inizio"], 1)
|
dati["durata"] = round(dati["fine"] - dati["inizio"], 1)
|
||||||
dati["stato"] = "OFF"
|
dati["stato"] = "OFF"
|
||||||
self.storico.appendleft(dati)
|
self.storico.appendleft(dati)
|
||||||
await self.broadcast({"evento": "chiamata_terminata", "dati": dati})
|
asyncio.create_task(self.broadcast({"evento": "chiamata_terminata", "dati": dati}))
|
||||||
|
|
||||||
async def watchdog_rx(self):
|
async def watchdog_rx(self):
|
||||||
while True:
|
while True:
|
||||||
@@ -147,7 +147,7 @@ class DashboardManager:
|
|||||||
ora = time.time()
|
ora = time.time()
|
||||||
for id_chiamata, dati in list(self.chiamate_attive.items()):
|
for id_chiamata, dati in list(self.chiamate_attive.items()):
|
||||||
if dati["direzione"] == "RX" and ora - dati.get("ultimo_frame", ora) > 1.5:
|
if dati["direzione"] == "RX" and ora - dati.get("ultimo_frame", ora) > 1.5:
|
||||||
await self.termina_chiamata(id_chiamata)
|
self.termina_chiamata(id_chiamata)
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# ENDPOINT WEB (aiohttp)
|
# ENDPOINT WEB (aiohttp)
|
||||||
@@ -353,10 +353,10 @@ class SessionManager:
|
|||||||
self.gestisci_ptt(sess, False)
|
self.gestisci_ptt(sess, False)
|
||||||
self.vocoder.rilascia_porta(f"SIP_{call_id}")
|
self.vocoder.rilascia_porta(f"SIP_{call_id}")
|
||||||
|
|
||||||
# PULIZIA FORZATA: Chiudiamo eventuali righe RX rimaste appese per questo interno
|
# Chiusura sincrona per evitare code
|
||||||
for id_dash in list(dashboard_app.chiamate_attive.keys()):
|
for id_dash in list(dashboard_app.chiamate_attive.keys()):
|
||||||
if id_dash.startswith("RX_") and id_dash.endswith(f"_{call_id}"):
|
if id_dash.startswith("RX_") and id_dash.endswith(f"_{call_id}"):
|
||||||
asyncio.create_task(dashboard_app.termina_chiamata(id_dash))
|
dashboard_app.termina_chiamata(id_dash)
|
||||||
|
|
||||||
del self.sessioni[call_id]
|
del self.sessioni[call_id]
|
||||||
asyncio.create_task(dashboard_app.broadcast({"evento": "estensioni_update"}))
|
asyncio.create_task(dashboard_app.broadcast({"evento": "estensioni_update"}))
|
||||||
@@ -372,11 +372,11 @@ class SessionManager:
|
|||||||
|
|
||||||
nome_base = get_nominativo(sess.dmr_id)
|
nome_base = get_nominativo(sess.dmr_id)
|
||||||
mittente_display = f"{nome_base} (Est. {sess.chiamante})"
|
mittente_display = f"{nome_base} (Est. {sess.chiamante})"
|
||||||
asyncio.create_task(dashboard_app.inizia_chiamata(id_dash_tx, "TX", mittente_display, sess.tg_destinazione))
|
dashboard_app.inizia_chiamata(id_dash_tx, "TX", mittente_display, sess.tg_destinazione)
|
||||||
elif stato is False and sess.ptt_attivo:
|
elif stato is False and sess.ptt_attivo:
|
||||||
sess.ptt_attivo = False
|
sess.ptt_attivo = False
|
||||||
if self.openbridge: self.openbridge.chiudi_flusso_chiamata(sess)
|
if self.openbridge: self.openbridge.chiudi_flusso_chiamata(sess)
|
||||||
asyncio.create_task(dashboard_app.termina_chiamata(id_dash_tx))
|
dashboard_app.termina_chiamata(id_dash_tx)
|
||||||
|
|
||||||
def gestisci_dtmf_digit(self, sess, digit):
|
def gestisci_dtmf_digit(self, sess, digit):
|
||||||
if sess.ptt_attivo: return
|
if sess.ptt_attivo: return
|
||||||
@@ -424,9 +424,9 @@ class SessionManager:
|
|||||||
|
|
||||||
if id_dash_rx not in dashboard_app.chiamate_attive:
|
if id_dash_rx not in dashboard_app.chiamate_attive:
|
||||||
dest_display = f"{sess.chiamante} (TG {tg_arrivo})"
|
dest_display = f"{sess.chiamante} (TG {tg_arrivo})"
|
||||||
asyncio.create_task(dashboard_app.inizia_chiamata(id_dash_rx, "RX", src_id, dest_display))
|
dashboard_app.inizia_chiamata(id_dash_rx, "RX", src_id, dest_display)
|
||||||
else:
|
else:
|
||||||
asyncio.create_task(dashboard_app.aggiorna_rx(id_dash_rx))
|
dashboard_app.aggiorna_rx(id_dash_rx)
|
||||||
|
|
||||||
if sess.ultimo_src_id != src_id:
|
if sess.ultimo_src_id != src_id:
|
||||||
sess.ultimo_src_id = src_id
|
sess.ultimo_src_id = src_id
|
||||||
@@ -540,9 +540,7 @@ class SipProtocol(asyncio.DatagramProtocol):
|
|||||||
def connection_made(self, transport): self.manager.sip_transport = transport
|
def connection_made(self, transport): self.manager.sip_transport = transport
|
||||||
def datagram_received(self, data, addr):
|
def datagram_received(self, data, addr):
|
||||||
if addr[0] != FREEPBX_IP and FREEPBX_IP != "0.0.0.0": return
|
if addr[0] != FREEPBX_IP and FREEPBX_IP != "0.0.0.0": return
|
||||||
msg = data.decode('utf-8', errors='ignore')
|
msg = data.decode('utf-8', errors='ignore').lstrip()
|
||||||
|
|
||||||
# FIX: splitlines() digerisce correttamente sia \r\n che \n
|
|
||||||
lines = msg.splitlines()
|
lines = msg.splitlines()
|
||||||
headers = {line.split(":", 1)[0].strip().upper(): line.split(":", 1)[1].strip() for line in lines[1:] if ":" in line}
|
headers = {line.split(":", 1)[0].strip().upper(): line.split(":", 1)[1].strip() for line in lines[1:] if ":" in line}
|
||||||
call_id = headers.get('CALL-ID', '')
|
call_id = headers.get('CALL-ID', '')
|
||||||
@@ -585,7 +583,6 @@ class SipProtocol(asyncio.DatagramProtocol):
|
|||||||
f"Max-Forwards: 70\r\nFrom: {headers.get('FROM', '')}\r\nTo: {headers.get('TO', '')}\r\n"
|
f"Max-Forwards: 70\r\nFrom: {headers.get('FROM', '')}\r\nTo: {headers.get('TO', '')}\r\n"
|
||||||
f"Call-ID: {call_id}\r\nCSeq: {headers.get('CSEQ', '').split()[0]} ACK\r\nContent-Length: 0\r\n\r\n")
|
f"Call-ID: {call_id}\r\nCSeq: {headers.get('CSEQ', '').split()[0]} ACK\r\nContent-Length: 0\r\n\r\n")
|
||||||
self.manager.sip_transport.sendto(ack.encode('utf-8'), addr)
|
self.manager.sip_transport.sendto(ack.encode('utf-8'), addr)
|
||||||
# FIX: Aggiunto supporto al CANCEL e chiusura forzata in dashboard
|
|
||||||
elif msg.startswith("BYE") or msg.startswith("CANCEL"):
|
elif msg.startswith("BYE") or msg.startswith("CANCEL"):
|
||||||
self.manager.termina_chiamata(call_id)
|
self.manager.termina_chiamata(call_id)
|
||||||
resp = (f"SIP/2.0 200 OK\r\nVia: {headers.get('VIA', '')}\r\nFrom: {headers.get('FROM', '')}\r\nTo: {headers.get('TO', '')}\r\n"
|
resp = (f"SIP/2.0 200 OK\r\nVia: {headers.get('VIA', '')}\r\nFrom: {headers.get('FROM', '')}\r\nTo: {headers.get('TO', '')}\r\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user