diff --git a/core.py b/core.py index aa1d4e9..1c627ec 100644 --- a/core.py +++ b/core.py @@ -98,7 +98,7 @@ def carica_rubrica(): UTENTI_SIP_DMR = carica_rubrica() # ==================================================================== -# DASHBOARD MANAGER (Motore Dati) +# DASHBOARD MANAGER (Motore Dati - Modificato Sincrono) # ==================================================================== class DashboardManager: def __init__(self): @@ -112,7 +112,7 @@ class DashboardManager: try: await ws.send_str(msg_str) 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_dest = get_nominativo(destinatario) @@ -126,20 +126,20 @@ class DashboardManager: "stato": "ON" } 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: 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: dati = self.chiamate_attive.pop(id_chiamata) dati["fine"] = time.time() dati["durata"] = round(dati["fine"] - dati["inizio"], 1) dati["stato"] = "OFF" 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): while True: @@ -147,7 +147,7 @@ class DashboardManager: ora = time.time() for id_chiamata, dati in list(self.chiamate_attive.items()): 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) @@ -353,10 +353,10 @@ class SessionManager: self.gestisci_ptt(sess, False) 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()): 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] asyncio.create_task(dashboard_app.broadcast({"evento": "estensioni_update"})) @@ -372,11 +372,11 @@ class SessionManager: nome_base = get_nominativo(sess.dmr_id) 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: sess.ptt_attivo = False 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): if sess.ptt_attivo: return @@ -424,9 +424,9 @@ class SessionManager: if id_dash_rx not in dashboard_app.chiamate_attive: 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: - asyncio.create_task(dashboard_app.aggiorna_rx(id_dash_rx)) + dashboard_app.aggiorna_rx(id_dash_rx) if 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 datagram_received(self, data, addr): if addr[0] != FREEPBX_IP and FREEPBX_IP != "0.0.0.0": return - msg = data.decode('utf-8', errors='ignore') - - # FIX: splitlines() digerisce correttamente sia \r\n che \n + msg = data.decode('utf-8', errors='ignore').lstrip() lines = msg.splitlines() 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', '') @@ -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"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) - # FIX: Aggiunto supporto al CANCEL e chiusura forzata in dashboard elif msg.startswith("BYE") or msg.startswith("CANCEL"): 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"