Connettersi a un sistema Asterisk operativo, ascoltandone gli eventi, permette di realizzare funzionalita' basate sullo stato delle chiamate in corso.

Ad esempio, possiamo aprire in automatico una finestra all'operatore che risponde al telefono, con tutte le informazioni sull'utente che sta chiamando.

Come funzionano i canali e i bridge di Asterisk

L'ascolto degli eventi puo' risultare complicato, perche' non esistono eventi semplici come "interno X ha chiamato Y".

Al contrario, l'ascolto avviene piu' a basso livello. Nel caso di "interno X ha chiamato Y", ecco quello che succede:

# I nomi dei canali e dei bridge sono inventati, per favorire la comprensibilita'.

# Utente X crea un canale
Evento Newchannel, nome canale -> CanaleUtente

# Viene creato un canale anche per Y
Evento Newchannel, nome canale -> CanaleLinea

# L'utente risponde, avvengono 3 eventi:
Evento BridgeCreate, nome bridge -> Bridge1
Evento BridgeEnter, CanaleUtente entra nel Bridge1
Evento BridgeEnter, CanaleLinea entra nel Bridge1

# Le due persone si parlano per un po'
# Al momento del riaggancio avvengono nuovamente 3 eventi
Evento BridgeLeave, CanaleUtente esce dal Bridge1
Evento BridgeLeave, CanaleLinea esce dal Bridge1
Evento BridgeDestroy, rimosso il bridge

# Nel caso di un trasferimento di chiamata le cose si complicano, con gli eventi BridgeMerge

L'elenco di tutti gli eventi AMI disponibili e' disponibile a questa pagina.

Attenzione alla versione di Asterisk consultata: gli eventi elencati possono variare in modo importante, cosi' come le loro proprieta'.

Esempio di connessione agli eventi AMI con Python

La prima cosa da fare e' configurare una nuova utenza per l'Asterisk Manager, nel file /etc/asterisk/manager.conf.

Di seguito un esempio di connessione ad Asterisk, utilizzando la libreria Panoramisk:

import asyncio
from panoramisk import Manager

manager = Manager(
    loop=asyncio.get_event_loop(),
    host="127.0.0.1",
    username="nome_utente",
    secret="password",
)


@manager.register_event("*")
def callback(manager, message):
    if "FullyBooted" not in message.event:
        print(message)


def main():
    manager.connect()
    try:
        manager.loop.run_forever()
    except KeyboardInterrupt:
        manager.loop.close()


if __name__ == "__main__":
    main()

Alternativa migliore, ma piu' complessa, a Panoramisk

Volendo, e' possibile utilizzare la libreria telnetlib standard di Python.

Dopo aver usato per diverso tempo Panoramisk e aver notato dei problemi sugli ambienti di produzione ad alto traffico, credo che usare direttamente telnetlib sia un approccio piu' valido.

Per iniziare, dai un'occhiata alle lezioni da 55 a 58 di questa playlist.