[RISOLTO] Blocco chiamate temporaneo per riunioni - Codici 9999/9998

Dan Dobrin

SOHO User
Advanced Certified
Registrato
28 Marzo 2024
Messaggi
8

Blocco Chiamate Temporaneo per Riunioni - Soluzione Funzionante​

Ciao a tutti! Dopo varie sperimentazioni sono riuscito a creare un sistema per bloccare temporaneamente le chiamate in ingresso durante le riunioni senza interferire con i messaggi fuori orario esistenti. Ve lo condivido perché so che molti hanno questa esigenza.

Il Problema​

Nel nostro ufficio avevamo bisogno di poter bloccare le chiamate durante briefing e riunioni importanti, ma senza perdere le configurazioni esistenti del centralino. Serviva qualcosa di semplice: componi un numero, si attiva il blocco con messaggio personalizzato, ricomponi un altro numero e torna tutto normale.

La Soluzione che Funziona​

Dopo vari tentativi con gli script di default che forzavano tutto il sistema fuori orario (e creavano casino), ho trovato questo approccio che funziona benissimo:

  • 9999 = Attiva blocco riunioni
  • 9998 = Disattiva blocco riunioni
  • Le chiamate bloccate sentono un messaggio tipo "Tutte le linee sono occupate per riunione interna, richiamate più tardi"
  • Il vero fuori orario continua a funzionare normalmente

Come Implementarlo​

Cosa Serve​

  • 3CX V20 (testato su Update 2+)
  • Accesso amministrativo
  • Un po' di pazienza per la configurazione iniziale

Passo 1: IVR per il Messaggio Riunioni​

Andate in Gestione chiamate → Digital Receptionist e create:

  • Nome: "IVR Riunioni" (o come preferite)
  • Numero interno: 83 (o uno libero)
  • Dipartimento: DEFAULT
  • Caricate il vostro file audio personalizzato
  • Timeout: 3 secondi → "Riattacca"
Il messaggio che uso io è: "Tutte le linee sono momentaneamente occupate per riunione interna. Sei pregato di chiamare più tardi. Grazie."

Passo 2: Script di Intercettazione​

Questo è il pezzo più importante. Andate in Integrazioni → Script di chiamata → Aggiungi dal negozio e scegliete timebasecallscript.cs.

Configurazione:

  • Nome: qualcosa tipo "intercetta_riunioni"
  • Quando eseguire: "Alla ricezione di una chiamata su un trunk"
  • Selezionate i vostri trunk principali
  • System Wide
Poi sostituite tutto il codice con questo (che ho testato e funziona):

#nullable disable<br>using CallFlow;<br>using System;<br>using System.IO;<br>using System.Threading;<br>using System.Threading.Tasks;<br>using TCX.Configuration;<br>using TCX.PBXAPI;<br>using System.Collections.Generic;<br>using System.Linq;<br>using CallFlow.CFD;<br><br>namespace interceptcall<br>{<br> public class InterceptInboundCall : ScriptBase&lt;InterceptInboundCall&gt;<br> {<br> const string DestinationDN = "83"; // Il vostro IVR riunioni<br> const string FlagPath = "/var/lib/3cxpbx/Instance1/Data/Logs/RIUNIONE_ATTIVA.flag";<br><br> public override async void Start()<br> {<br> try<br> {<br> await Task.Run(async () =&gt;<br> {<br> try<br> {<br> MyCall.Debug($"Chiamata in arrivo: {DateTime.UtcNow}");<br> bool intercepted = false;<br> var ps = MyCall.PS as PhoneSystem;<br><br> if (MyCall.Caller.DN is ExternalLine externalLine)<br> {<br> var DIDNumber = MyCall.Caller["inbound_did"];<br> var CallerID = MyCall.Caller.CallerID;<br><br> // Qui è la magia: controlliamo se esiste il file flag<br> if (File.Exists(FlagPath))<br> {<br> var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN));<br><br> try<br> {<br> var result = await MyCall.RouteToAsync(destination_struct);<br> MyCall.Info($"Chiamata da {CallerID} reindirizzata per riunioni");<br> intercepted = true;<br> }<br> catch (Exception ex)<br> {<br> MyCall.Error($"Errore nel redirect: {ex}");<br> }<br> }<br> else<br> {<br> MyCall.Debug($"Nessuna riunione attiva, routing normale");<br> }<br> }<br><br> MyCall.Return(intercepted);<br> }<br> catch (Exception ex)<br> {<br> MyCall.Error($"Errore script: {ex}");<br> MyCall.Return(false);<br> }<br> });<br> }<br> catch (Exception ex)<br> {<br> MyCall.Error($"Errore critico: {ex}");<br> MyCall.Return(false);<br> }<br> }<br> }<br>}<br>

Passo 3: Script per Attivazione (9999)​

Sempre in Integrazioni → Script di chiamata, aggiungi dal negozio extavailable.cs:

  • Nome: "attiva_riunioni"
  • Codice di composizione: 9999
  • System Wide
Codice da usare:

using System;<br>using System.IO;<br>using System.Threading.Tasks;<br>using TCX.Configuration;<br>using CallFlow;<br>using System.Linq;<br>using System.Collections.Generic;<br><br>namespace dummy<br>{<br> public class AttivaRiunioni : ScriptBase&lt;AttivaRiunioni&gt;<br> {<br> public override async Task&lt;bool&gt; StartAsync()<br> {<br> const string FlagPath = "/var/lib/3cxpbx/Instance1/Data/Logs/RIUNIONE_ATTIVA.flag";<br> <br> if (MyCall.Caller.DN is Extension ext &amp;&amp; MyCall.ReferredByDN is not DN)<br> {<br> try<br> {<br> await File.WriteAllTextAsync(FlagPath, DateTime.Now.ToString());<br> MyCall.Info($"Riunioni attivate da interno {ext.Number}");<br> <br> // Messaggio di conferma (potete cambiarlo)<br> try<br> {<br> await MyCall.AssureMedia()<br> .ContinueWith(_ =&gt; MyCall.PlayPrompt(ext.GetPropertyValue("PROMPTSETID"), ["ST_CUSTOM1_SET"], PlayPromptOptions.Blocked))<br> .Unwrap();<br> }<br> catch<br> {<br> // Se non va il messaggio pazienza, l'importante è che funzioni<br> }<br> <br> return true;<br> }<br> catch (Exception ex)<br> {<br> MyCall.Info($"Errore: {ex.Message}");<br> return false;<br> }<br> }<br> <br> return false;<br> }<br> }<br>}<br>

Passo 4: Script per Disattivazione (9998)​

Stesso procedimento, ma con codice 9998:

using System;<br>using System.IO;<br>using System.Threading.Tasks;<br>using TCX.Configuration;<br>using CallFlow;<br>using System.Linq;<br>using System.Collections.Generic;<br><br>namespace dummy<br>{<br> public class DisattivaRiunioni : ScriptBase&lt;DisattivaRiunioni&gt;<br> {<br> public override async Task&lt;bool&gt; StartAsync()<br> {<br> const string FlagPath = "/var/lib/3cxpbx/Instance1/Data/Logs/RIUNIONE_ATTIVA.flag";<br> <br> if (MyCall.Caller.DN is Extension ext &amp;&amp; MyCall.ReferredByDN is not DN)<br> {<br> try<br> {<br> if (File.Exists(FlagPath))<br> {<br> File.Delete(FlagPath);<br> MyCall.Info($"Riunioni disattivate da interno {ext.Number}");<br> }<br> <br> try<br> {<br> await MyCall.AssureMedia()<br> .ContinueWith(_ =&gt; MyCall.PlayPrompt(ext.GetPropertyValue("PROMPTSETID"), ["ST_CUSTOM2_SET"], PlayPromptOptions.Blocked))<br> .Unwrap();<br> }<br> catch<br> {<br> // Stesso discorso di prima<br> }<br> <br> return true;<br> }<br> catch (Exception ex)<br> {<br> MyCall.Info($"Errore: {ex.Message}");<br> return false;<br> }<br> }<br> <br> return false;<br> }<br> }<br>}<br>

Come Testarlo​

  1. Componete 9999 - dovreste sentire "Profilo personalizzato 1 imposta stato" (o il vostro messaggio custom)
  2. Fate chiamare qualcuno da fuori - dovrebbe sentire il vostro messaggio riunioni
  3. Componete 9998 - si disattiva
  4. Fate richiamare - dovrebbe squillare normalmente

Personalizzazioni Utili​

Cambiare i Codici​

Facilissimo: quando create gli script, mettete il codice che preferite invece di 9999/9998.

Messaggi Audio Personalizzati​

Ho trovato tre modi che funzionano:

Opzione 1 - Prompt di Sistema (la più affidabile): Andate in Impostazioni → Prompt di sistema → Italian Prompts Set e cercate ST_CUSTOM1_SET e ST_CUSTOM2_SET. Sostituite quei file con i vostri messaggi tipo "Modalità riunioni attivata" e "Modalità riunioni disattivata".

Opzione 2 - File negli Script: Se vedete una sezione "File audio" sotto l'editor di codice degli script, potete caricare lì i vostri file e modificare il codice per usarli:

["nome_vostro_file.wav"] // con .wav<br>
Opzione 3 - Cambiare il messaggio principale: Nell'IVR Riunioni potete sempre cambiare il file audio con quello che preferite.

Specifiche per i File Audio​

Dopo vari tentativi, questi formati funzionano sempre:

  • WAV, 8kHz, Mono, 16-bit
  • Durata massima 30 secondi per i prompt, 60 per l'IVR
  • Evitate file troppo grossi

Note Finali​

Questo sistema l'ho sviluppato perché quello che trovavo in giro era troppo invasivo o non funzionava bene. I vantaggi principali:

  • Non tocca le configurazioni esistenti
  • È completamente reversibile
  • Non interferisce con il vero fuori orario
  • È semplice da usare
Testato su 3CX V20 Enterprise. Se qualcuno lo migliora o trova bug, fatemi sapere!
 

Allegati

Inizia con 3CX – Admin

Forum statistics

Discussioni
44.658
Messaggi
233.413
Membri
78.444
Ultimo Iscritto
PCCAdmin