
IP ATC Asterisk je mocný nástroj v oblasti IP telefonie. Webové rozhraní FreePBX, vytvořené pro Asterisk, výrazně usnadňuje nastavení a snižuje prahovou hodnotu pro vstup do systému.
Pokud dokážete vymyslet jakýkoli úkol související s IP telefonie, téměř určitě to lze realizovat v Asterisk. Ale buďte si jisti, že budete potřebovat vytrvalost a odhodlání.
Stál před námi úkol nastavit e-mailová upozornění na zmeškané hovory. Přesněji řečeno, upozorňovat prostřednictvím e-mailu na ty případy, kdy příchozí hovor přešel do fronty, ale nikdo (z agentů) na tento příchozí hovor neodpověděl.
Překvapivě jsme nenalezli žádné standardní prostředky pro řešení tohoto úkolu ve FreePBX. O tom, jak jsme tento úkol vyřešili, se podělím dále.
Úvod
Před tím, než jsme se pustili do úkolu "přímo", jsme samozřejmě hledali informace na internetu, ale klíčová řešení jsme nenalezli (možná jsme hledali špatně, ale co se dá dělat...).
Zkušeností s přímou prací v Asterisk není tolik, kolik bychom si přáli, a proto bylo navržené řešení , nebylo do detailu promyšleno a bylo odmítnuto.
Líbilo se nám řešení, které navrhl , i když nefungovalo. Z toho vyplývá, že je třeba pracovat v Asterisk v kontextu front [ext-queues]. A jelikož pracujeme ve FreePBX, je třeba pracovat v konfiguračním souboru "extensions_override_freepbx.conf". Všimli jsme si, že "zachytit zmeškané hovory" je pohodlné před událostí hangupcall (ukončení hovoru).
Po přečtení diskuse , se objevila myšlenka, že je třeba filtrovat v CDR proměnnou „Disposition“ pro všechny agenty ve frontě. A po přečtení informace se utvořily velmi konkrétní kroky k vyřešení stanoveného úkolu.
Co máme:
Máme FreePBX 13.0.197, který používá Asterisk 13.12.1. Verze OS SHMZ release 6.6 (Final). Distribuce je postavena na CentOS.
V Asterisk je nastaven IVR (hlasové menu), které rozděluje příchozí hovory do různých front (Queues). Každé frontě jsou přiděleni Agent (agenti), tedy operátoři.
Teorie
Co se děje v Asterisk
Když do Asterisk přijde příchozí hovor, tento hovor se dostane na IVR. Volající si vybere stisknutím určitého čísla na telefonu a dostane se do určité fronty. Poté všem volným agentům fronty zároveň přijde hovor.
Abychom lépe pochopili, co se v tuto chvíli děje a co následně, podívejme se na Report CDR (Obr.1).

Obr.1
Když příchozí hovor skončil v čekání, hodnota proměnné „Disposition“ u všech agentů se nastavila na „NO ANSWER“, pokud agenti nebyli v tu chvíli zaneprázdněni. Proměnná „Disposition“ mohla mít i jiné hodnoty (viz. ), kromě hodnoty „ANSWERED“. V okamžiku, kdy některý z agentů zvedne příchozí hovor, hodnota proměnné „Disposition“ tohoto agenta se stává „ANSWERED“.
Z Reportu CDR lze poznamenat, že když hovor přešel do fronty (ve sloupci App hodnota se stává „Queue“), všechny události se objevují se stejným „uniqueid“ (sloupec System).
Stručně o CDR
Je důležité pochopit, co je CDR, a v jakém okamžiku se do CDR zapisují údaje, které pozorujeme v Reportu CDR. CDR, ve vztahu k operačnímu systému — je databáze, do které Asterisk zapisuje podrobnou zprávu o hovorech (viz. ). V našem případě je to databáze s názvem asteriskcdrdb, která se nachází v mysql. Experimentálně jsme zjistili, že údaje o hovoru s určitou hodnotou „uniqueid“ se zapisují do asteriskcdrdb ne ihned po vzniku nějaké události, ale až po události hangupcall (ukončení hovoru).
Princip fungování vytvořeného řešení
Jelikož máme více znalostí v bash než v Asterisku, základní myšlenka byla následující. Před událostí hangupcall zavolejte bash skript. Do tohoto skriptu předajte 3 parametry. První parametr „uniqueid“, pro filtrování údajů získaných z CDR. Druhý parametr „CALLERID(num)“ (číslo volajícího), abychom věděli, komu zavolat zpět. Třetí parametr „NODEST“ (číslo fronty), do které hovor přišel, abychom věděli, o čem hovor byl, a komu poslat e-mailovou notifikaci o zmeškaném hovoru.
Bash skript se musí připojit k databázi asteriskcdrdb v mysql a získat všechny hodnoty proměnné „Disposition“ s daným „uniqueid“. Získané údaje je třeba vyloučit hodnoty: „NO ANSWER“, „BUSY“, „FAILED“, „UNKNOWN“. Výsledkem budou buď „ANSWERED“ — na příchozí hovor bylo odpovězeno, nebo nic — zmeškaný hovor.
Pokud hovor byl zmeškaný, skript by měl poslat e-mailové oznámení.
Předem bych chtěl zdůraznit důležitý bod. Asterisk vykonává příkazy postupně, čekající na jejich dokončení (což je logické). Bash skript budeme volat dříve, než se provede příkaz hangupcall. Tím pádem během okamžiku vykonání skriptu informace o hledaném 'uniqueid' ještě nebude zapsána do CDR. Abychom tento problém vyřešili, zavoláme bash skript s parametrem '&', aby Asterisk okamžitě přešel k vykonání dalšího kroku, t.j. hangupcall. A uvnitř bash skriptu, na jeho začátku, nastavíme krátké zpoždění, abychom dali Asterisk času zapsat potřebná data s 'uniqueid' do CDR.
Praxe
Než přejdeme k nastavení Asterisk a vytvoření bash skriptu, je nutné nastavit posílání e-mailových upozornění. K tomu použijeme nástroj postfix.
Nastavení postfix
Máme doménu pro poštu 'lucky.ru', která je umístěna na Yandexu. Nastavíme postfix do režimu smtp klienta a budeme posílat e-maily z účtu asterisk@lucky.ru.
Základem je tato volba: .
Nejprve nainstalujeme/aktualizujeme/zkontrolujeme přítomnost balíčků:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainNebudeme přepisovat hlavní konfigurační soubor postfix '/etc/postfix/main.cf', ale vytvoříme jeho zálohu:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savUpravíme soubor '/etc/postfix/main.cf' tak, aby měl následující podobu:
nano /etc/postfix/main.cf
#####################
relayhost =
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/private/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_type = cyrus
smtp_sasl_mechanism_filter = login
smtp_sender_dependent_authentication = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/private/sender_relay
smtp_generic_maps = hash:/etc/postfix/generic
smtp_tls_CAfile = /etc/postfix/ca.pem
smtp_use_tls = yes
smtputf8_autodetect_classes = all
#####################Ne každou řádku v '/etc/postfix/main.cf' lze komentovat. Některé řádky nejsou parserem rozpoznány jako komentáře a jsou předány k zpracování, což může vést k chybám. Je lepší se komentářům v tomto souboru vyhnout. Můžete to vyzkoušet spuštěním 'tail -f /var/log/messages' v sousedním okně.
Rád bych vyzdvihl řádek 'smtputf8_autodetect_classes = all'. Tento záznam zapíná utf-8 jako výchozí, což umožňuje používat cyrilici jak v těle e-mailu, tak v předmětu bez dalších manipulací (viz. ).
Vytvoříme adresář pro konfigurační soubory:
mkdir /etc/postfix/privateUpravujeme soubor „/etc/postfix/private/sender_relay“. V něm je třeba uvést, na který smtp server se odkazovat při použití naší e-mailové domény:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Upravujeme soubor „/etc/postfix/private/sasl_passwd“. V něm uvedeme e-mailovou adresu, kterou budeme používat k odesílání e-mailů, a také uživatelské jméno a heslo k tomuto účtu (uživatelské jméno a heslo uvádíme přes dvojtečku):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Upravujeme soubor „/etc/postfix/generic“. V něm uvedeme pravidla pro substituci odesílací adresy (viz. ):
nano /etc/postfix/generic
#####################
root asterisk@lucky.ru
root@localhost asterisk@lucky.ru
root@localhost.localdomain asterisk@lucky.ru
root@freepbx asterisk@lucky.ru
root@freepbx.localdomain asterisk@lucky.ru
root@asterisk asterisk@lucky.ru
root@asterisk.localdomain asterisk@lucky.ru
asterisk asterisk@lucky.ru
asterisk@localhost asterisk@lucky.ru
asterisk@localhost.localdomain asterisk@lucky.ru
asterisk@freepbx asterisk@lucky.ru
asterisk@freepbx.localdomain asterisk@lucky.ru
asterisk@asterisk asterisk@lucky.ru
asterisk@asterisk.localdomain asterisk@lucky.ru
root@localdomain.localdomain asterisk@lucky.ru
#####################Původní odesílací adresa závisí na obsahu „/etc/hosts“ a „/etc/hostname“, stejně jako na uživatelském jménu, které bude e-mail odesílat. Tedy i když používáme smtp klienta a odesíláme e-maily z asterisk@lucky.ru, postfix stejně na začátku nastaví „něco vlastního“ jako odesílatele a je třeba to opravit pravidly z tohoto konfiguračního souboru.
Uvedu obsah svého souboru „/etc/hosts“:
cat /etc/hosts
#####################
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 asterisk.localdomain
127.0.0.1 localhost.localdomain localhost
::1 asterisk localhost localhost6
#####################Je důležité, aby server měl nějakou doménu (hodnota za tečkou), protože nástroj mail „hledá“ jméno domény v „/etc/hosts“ a pokud jej „nerozpozná“ hned, bude v tom pokračovat ještě několik minut, a teprve potom odešle e-mail. Tedy pokud doména není uvedena, e-mail bude odcházet se zpožděním několika minut.
Uvedu obsah svého souboru „/etc/hostname“:
cat /etc/hostname
#####################
asterisk
#####################Dále je třeba převést vytvořené konfigurační soubory do indexovaných databází, k tomu provedeme následující příkaz:
postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}Dále je třeba stáhnout a umístit na server certifikát smtp.yandex.ru, k tomu provedeme následující příkaz:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemAle poté, co se na obrazovce objeví technické informace, tým bude ‚pokračovat v zavěšení‘. Stiskněte Ctrl+C pro přerušení.
Nyní ručně odstraníme z výsledného souboru všechny zbytečnosti a ponecháme pouze certifikát. Mělo by to vypadat přibližně takto:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################A nakonec restartujeme postfix:
service postfix restartOdesíláme testovací e-mail:
echo "Toto je tělo e-mailu" | mail -s "Toto je předmět" admin@lucky.ruadmin@lucky.ru — cílová adresa
Tímto je nastavení posfixu dokončeno.
Píšeme bash skript
Vytvoříme adresář pro ukládání bash skriptu (tady to může být kdekoli, jak se komu líbí):
mkdir /home/asterisk/scriptsVytváříme soubor bash skriptu:
touch /home/asterisk/scripts/noanswer.shPřidělujeme skriptu práva na spuštění:
chmod +x /home/asterisk/scripts/noanswer.shPokud máte pochybnosti o právech k souboru, můžete při ladění na chvíli poskytnout plný přístup k souboru. Ale to není „bezpečné“.
chmod 777 /home/asterisk/scripts/noanswer.shText bash skriptu:
nano /home/asterisk/scripts/noanswer.sh
#####################
#! /bin/bash
sleep 7
res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"
answer=`mysql -u freepbxuser -pPassword_freepbxuser -D asteriskcdrdb -B -N -e "$res_sql" | grep -E -v "NO ANSWER|BUSY|FAILED|UNKNOWN" | head -n 1`
error_kod=0
if [ "$answer" != "ANSWERED" ]
then
case $3 in
68800)
address="big_boss@lucky.ru"
subject="o důležitém tématu"
;;
63100)
address="debian@lucky.ru"
subject="o otázkách linux debian"
;;
63200)
address="windows@lucky.ru"
subject="o otázkách windows"
;;
63300)
address="freebsd@lucky.ru"
subject="o otázkách freebsd"
;;
63400)
address="ubuntu@lucky.ru"
subject="o otázkách linux ubuntu"
;;
63500)
address="centos@lucky.ru"
subject="o otázkách linux centos"
;;
*)
address="admin@lucky.ru"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Zmeškaný hovor od předplatitele $2, který volal $subject." | mail -s "Zmeškaný hovor od $2" $address
echo "Zmeškaný hovor pro $address od předplatitele $2, který volal $subject. uid=$1" | mail -s "Zmeškaný hovor od $2" admin@lucky.ru
;;
1)
echo "Zmeškaný hovor od předplatitele $2. Neznámý seznam. uid=$1" | mail -s "Zmeškaný hovor od $2" admin@lucky.ru
;;
esac
fi
#####################Krátké shrnutí skriptu:
„sleep 7“:
To je ta zpoždění, o které jsem mluvil dříve. Měli jsme nastavené zpoždění na 7 sekund. I když si myslím, že jedna sekunda by úplně stačila.
„res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"“:Dotaz v mysql jsme umístili do samostatné proměnné pro pohodlí.
Dále provádíme dotaz na mysql a filtrujeme získaný výstup. Odstraňujeme všechny možnosti kromě "ANSWERED", pokud vůbec existují. Pokud je několik hodnot "ANSWERED", ponecháme pouze jednu. Na konci proměnné "answer" získáme buď "ANSWERED", nebo "".
Pokud hodnota proměnné "answer" není "ANSWERED", jde o zmeškaný hovor. V závislosti na čísle fronty pomocí operátoru case určíme adresu, na kterou je třeba odeslat e-mailové upozornění, a co přesně v tomto sdělení napsat (změnitelná část zprávy).
Dále zvažujeme možnost, kdy je fronta nastavena v Asterisk, ale není popsána ve skriptu. V tomto případě obdrží e-mail na admin@lucky.ru, že fronta není skriptu známa.
Pokud je fronta popsána, bude odesláno e-mailové sdělení na správnou adresu a duplicita e-mailu na admin@lucky.ru s uvedením "uniqueid", aby bylo možné sledovat události spojené s tímto hovorem, pokud to bude nutné.
Tímto skript končí.
Poznamenám, že pro připojení k mysql jsme použili přihlašovací jméno a heslo, které jsme si předem zjistili. Ve FreePBX, abyste zjistili přihlašovací jméno uživatele Asterisk v mysql, proveďte následující příkaz:
cat /etc/amportal.conf | grep AMPDBUSERA abyste zjistili heslo uživatele Asterisk v mysql, proveďte následující příkaz:
cat /etc/amportal.conf | grep AMPDBPASSNastavení Asterisk
Používáme FreePBX. Ve FreePBX existují různé typy konfiguračních souborů (viz ), některé z nich FreePBX přepisuje při restartování, a některé ne (nazývají se custom), protože jsou speciálně určeny pro uživatele.
Budeme pracovat se souborem konfigurace "extensions_override_freepbx.conf", protože patří do typu custom.
Nejprve se ujistíme, že je v souboru "/etc/asterisk/extensions.conf" připojen soubor "extensions_override_freepbx.conf". K tomu provedeme následující příkaz:
cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################Upravíme soubor "/etc/asterisk/extensions_override_freepbx.conf" a uvedeme ho do následující podoby:
nano /etc/asterisk/extensions_override_freepbx.conf
#####################
[ext-queues]
exten => h,1,System(/home/asterisk/scripts/noanswer.sh ${CDR(uniqueid)} ${CALLERID(num)} ${NODEST} &)
exten => h,2,Macro(hangupcall,)
#####################Jak jsem již napsal, je nezbytné použít symbol „&“ na konci. Protože budeme pracovat v bash skriptu s daty CDR přímo z databáze MySQL, která se do MySQL ukládá pouze po provedení „exten => h,2,Macro(hangupcall,)“, není třeba čekat na dokončení běhu bash skriptu, ale je třeba přejít k provedení dalšího kroku v Asterisku. A samotný bash skript by měl obsahovat časové zpoždění před provedením své hlavní části.
Aby změny v konfiguračním souboru „/etc/asterisk/extensions_override_freepbx.conf“ nabyly účinnosti, je nutné restartovat jádro Asterisku následujícím příkazem:
/usr/sbin/asterisk -rx "core restart now"Toto je třeba provést poté, co bude bash skript vytvořen.
Závěr
To je pravděpodobně 1001. způsob „chycení zmeškaných hovorů“ v Asterisku. Podělte se v komentářích, jak tuto úlohu řešíte vy. A co podle vás lze vylepšit/předělat/optimalizovat. Budeme vděčni za konstruktivní nápady.
Zdroj: habr.com
