Konfigurace Asterisku (3) - extensions.conf

V tomto dílu si ukážeme základy dialplanu. Dialplan je srdce Asterisku. Je to konfigurace, která určuje, jak má Asterisk zpracovávat hovory. Dialplan je uložený v souboru extensions.conf. Tento soubor je nezávislý na technologii; to je jedna ze silných stránek Asterisku. Díky tomu lze Asterisk snadno použít jako bránu mezi různými technologiemi.

Extensions a kontexty

Jak jsme psali v minulém dílu, Asterisk je koncepčně obdobou klasické telefonní ústředny, ke které jsou všechna zařízení připojena do "zásuvek", zvaných extensions. Extensions mohou používat různé technologie. Nejčastější je protokol SIPi, ale je možné použít i protokol H323, speciální kartu pro připojení analogových telefonů, ISDNi apod.

Je dobré si uvědomit, že i když každý telefon má svojí extension, naopak to neplatí. Například ústředna operátora, který poskytuje propojení do klasické telefonní sítě, je z hlediska Asterisku také extension. Je to jen "lepší zásuvka", do které lze připojit tlustý kabel, který umožňuje vést víc hovorů naráz. Takovému spoji se často říká trunk. Extension tedy nemusí představovat jen jeden telefon, ale může to být i linka do zbytku telefonní sítě.

Každá extension má vlastnost context (viz minulý díl), která určuje, jaká část konfiguračního souboru extensions.conf se použije pro hovory, které z ní přicházejí. Každý kontext má tedy přiřazenou skupinu extensions. Začneme s velmi jednoduchou variantou extensions.conf:

[uctarna]

exten => 998,1,Answer()
exten => 998,2,Hangup()

[marketing]

exten => 999,1,Answer()
exten => 999,2,Hangup()

V tomto případě jsme definovali dva kontexty. Jeden s názvem uctarna a druhý s názvem marketing. Jména kontextů jsou vždy v hranatých závorkách. Rozdělení telefonů do dvou kontextů nám umožňuje nastavit odlišné chování ústředny pro volání z marketingu a pro volání z účtárny.

Pravidla

Konfigurace v každém kontextu se skládá z jednotlivých pravidel. Každé pravidlo začíná klíčovým slovem exten a má tvar

exten => name,priority,application

Probereme si všechny tři části pravidla:

name
Pravidlo se použije, odpovídá-li volané číslo hodnotě name. Nejjednodušší možnost je použít přímo telefonní číslo, tak jak je to uvedeno v příkladu. Některé telefony (a většina SIPových telefonů) umožňují místo čísla použít obecný text. Asterisk tuto možnost podporuje, name může obsahovat i písmena a hvězdičku. V praxi se často využívají šablony, které umožňují jedním pravidlem ošetřit celou skupinu hodnot. Šablony se liší od obyčejných hodnot tím, že začínají znakem podtržítko. Například _XXX odpovídá všem trojciferným číslům. K šablonám se ještě vrátíme. Chcete-li v name použít znak křížek (#), musíte použít šablonu, jinak nepochodíte. Je to jedna z velmi mnoha specialit Asterisku. Některé hodnoty name mají speciální význam, většinou jde o samostatná písmena jako h, i apod.
priority
Priorita určuje pořadí zpracování záznamů. Asterisk během zpracování hovoru postupně probírá pravidla a řadí je přitom podle priority. Nejprve hledá odpovídající pravidlo s prioritou 1, potom hledá pravidlo s prioritou 2, atd. Žádné číslo nesmí být vynecháno. Pokud by kontext obsahoval jen pravidla s prioritami 1, 2 a 4, pak by Asterisk zpracoval priority 1 a 2, následně by nenašel pravidlo s prioritou 3 a v hledání dalších pravidel by už nepokračoval. Na pravidlo s prioritou 4 by nikdy nedošlo.
application
application je příkaz, který se má provést. Aplikací, neboli příkazů, jsou desítky a v rámci seriálu se většinu z nich postupně naučíme. Seznam použitelných příkazů závisí na tom, jaké moduly byly nahrány při startu asterisku. Některé příkazy mají parametry, které se píší do kulatých závorek za příkaz (viz například Ringing níže).

Příkazy

V našem příkladu bude účtárně fungovat jen jedno telefonní číslo 998, které po zavolání spojí hovor (příkaz Answer) a okamžitě zavěsí (Hangup). Taková konfigurace není moc užitečná, pojďme ji rozšířit o další příkazy. Při každé změně dialplanu (souboru extensions.conf) je potřeba provést v konzoli Asterisku příkaz dialplan reload, aby se změny projevily.


astest*CLI> dialplan reload
Dialplan reloaded.
astest*CLI>

Příkaz Ringing() signalizuje volajícímu, že volaný telefon vyzvání. Při použití Ringing ve skutečnosti "vyzvání" Asterisk, ale to je jen technický detail. Ringing se používá například před vstupem do hlasového automatu. Pro volajícího je příjemnější, když napřed uslyší cílový systém aspoň dvakrát zazvonit, než dojde ke spojení.

Další příkaz Wait(seconds) umožňuje nastavit jak dlouho bude Asterisk vyzvánět. Wait prostě pozastaví provádění dialplanu na zadaný počet sekund. Náš příklad s účtárnou by mohl vypadat například takto:

[uctarna]

exten => 998,1,Ringing()
exten => 998,2,Wait(2)
exten => 998,3,Answer()
exten => 998,4,Hangup()

Tato konfigurace se dá zapsat trochu jiným způsobem:

[uctarna]

exten => 998,1,Ringing()
exten => 998,n,Wait(2)
exten => 998,n,Answer()
exten => 998,n,Hangup()

Priorita n (next) je zkratka, která znamená prioritu o 1 větší než byla priorita u předchozího pravidla se stejnou hodnotou name. I když se obě varianty neliší funkcí, druhý případ se mnohem lépe upravuje. Vynechání nějakého čísla priority je častou chybou při psaní konfigurace.

Jak je vidět, zpracování hovoru může Asterisku zabrat nějaký čas. Pokud se sejde více hovorů ve stejnou dobu, bude je Asterisk zpracovávat současně nezávisle na sobě, a to i když patří do stejného kontextu. Konfigurace Asterisku je vlastně paralelní programování.

Chování Asterisku připomíná naštvanou úřednici, která po dvou vteřinách zdvihne sluhátko a okamžitě ho zase zavěsí, aby telefon přestal zvonit. Pokud by byl hovor tarifikován, zaplatil by volající poplatek za spojení hovoru. Chcete-li aby Asterisk odmítnul hovor, můžete použít příkaz Busy, který volajícímu signalizuje "obsazeno" a čeká až volající zavěsí (podle dokumentace). Protokol SIP neposílá zprávy o zavěšení sluchátka v případě odmítnutí hovoru volaným, takže je-li volající připojen přes SIP, nebude Busy čekat na zavěšení, ale skončí prakticky hned.

[uctarna]

exten => 998,1,Ringing()
exten => 998,n,Wait(2)
exten => 998,n,Busy()

Ve skutečnosti můžete místo Busy použít i Hangup (bez předchozího Answer), výsledný efekt bude velmi podobný. (U extension typu SIP signalizuje Busy "obsazeno" a Hangup "odmítnuto uživatelem".) Oba příkazy mají společnou vlastnost, že ukončují zpracování pravidel pro volané číslo. Pokud by za příkazem Busy bylo další pravidlo, Asterisk by ho už neprováděl.

Pro experimenty s Asteriskem je je velmi užitečný příkaz Playback(filename), který přehraje soubor se zvukovým záznamem. Asterisk hledá soubory v adresáři /usr/share/asterisk/sounds/ (lze změnit v asterisk.conf). V tomto adresáři jsou standartní hlášky nainstalované současně s Asteriskem. Parametr filename je jméno souboru bez přípony.

[uctarna]

exten => 998,1,Ringing()
exten => 998,n,Wait(2)
exten => 998,n,Answer()
exten => 998,n,Playback(hello-world)
exten => 998,n,Hangup()

K hláškám se v tomto seriálu ještě vrátíme. Ukážeme si jak nainstalovat české hlášky a jak vyrobit vlastní. Kromě souboru hello-world můžete použít i další nahrávky jako například beep, digits/0, digits/1, ...

Nakonec připomeneme příkaz Dial(type/identifier), který přepojí hovor na danou extension. Příklad najdete v minulém dílu. Dial má mnoho parametrů, které by vydaly na celý další díl. Nejdůležitější je první parametr, který říká kam se má hovor přepojit. Před lomítkem je typ extension, například SIP. Asterisk pak hledá extension definované v příslušném konfigurčním souboru (sip.conf). Jméno extension je za lomítkem.

Ladění

Na závěr si ukážeme jeden velmi užitečný příkaz, který se hodí pro ladění konfigurace.

[uctarna]

exten => 998,1,NoOp(nekdo nam vola, vyzvanim)
exten => 998,n,Ringing()
exten => 998,n,NoOp(cekam)
exten => 998,n,Wait(2)
exten => 998,n,NoOp(koncim)
exten => 998,n,Busy()
exten => 998,n,NoOp(na tohle nikdy nedojde)

Příkaz NoOp(message) vypíše na konzoli Asteriku parametr message. Aby byl výstup příkazu NoOp na konzoli vidět, musíte v konzoli nastavit úroveň logování 3 nebo víc:

astest*CLI> core set verbose 3
Verbosity was 0 and is now 3
astest*CLI>

Hlavní využití příkazu NoOp spočívá ve výpisu proměnných dialplanu, to už se ale do tohoto dílu nevejde.

Dialplan lze vypsat pomocí konzolového příkazu dialplan show. Pokud dialplan nefunguje tak jak má, můžete zjistit co přesně si Asterisk "odnesl" z extensions.conf.

astest*CLI> dialplan show
[ Context 'uctarna' created by 'pbx_config' ]
  '998' =>          1. Ringing()                                  [pbx_config]
                    2. Wait(2)                                    [pbx_config]
                    3. Busy()                                     [pbx_config]

-= 1 extension (3 priorities) in 1 context. =-
astest*CLI>

Nastavení core set verbose 3 také způsobí výpis následujících ladících hlášek:

    -- Executing [998@uctarna:1] Ringing("SIP/cerny-09c2b570", "") in new stack
    -- Executing [998@uctarna:2] Wait("SIP/cerny-09c2b570", "2") in new stack
    -- Executing [998@uctarna:3] Busy("SIP/cerny-09c2b570", "") in new stack
  == Spawn extension (uctarna, 998, 3) exited non-zero on 'SIP/cerny-09c2b570'

Smysl je celkem zřejmý. V hranaté závorce je volané číslo, kontext a číslo priority. Za hranatou závorkou je příkaz, který Asterisk vykonává.

Závěr

Ukázali jsme některé základní koncepty dialplanu, jako pravidla a jejich priority. V příštím dílu se budeme věnovat konfiguraci trunku a ukážeme si jak Asterisk s pomocí providera propojit s veřejnou telefonní sítí.

Doufám, že v článcích o konfiguraci Asterisku budete dále pokračovat, velmi se těším. Zároveň Vám přeji mnoho úspěchů
a dlouhou" životnost" těchto stránek.

S pozdravem
Václav Kořán