Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Sigurno su mnogi od vas, poput mene, imali ideju da urade nešto jedinstveno. U ovom članku ću opisati tehničke probleme i rješenja s kojima sam se morao suočiti prilikom razvoja PBX-a. Možda će to nekome pomoći da se odluči za svoju ideju, a nekome da krene utabanim putem, jer i meni je dobro došlo iskustvo pionira.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Ideja i ključni zahtjevi

A sve je počelo jednostavno s ljubavlju prema Asterisk (okvir za izgradnju komunikacijskih aplikacija), automatizacija telefonije i instalacija freepbx (web interfejs za Asterisk). Ako su potrebe kompanije bile bez specifičnosti i spadale u okvire mogućnosti freepbx - sve je super. Celokupna instalacija je obavljena u roku od XNUMX sata, kompanija je dobila konfigurisanu centralu, korisničko sučelje i kratku obuku plus podršku po želji.

Ali najzanimljiviji zadaci su bili nestandardni i onda nije bilo tako fantastično. Asterisk može mnogo, ali da bi web interfejs bio u ispravnom stanju, bilo je potrebno potrošiti višestruko više vremena. Dakle, mali detalj može potrajati mnogo duže od instaliranja ostatka PBX-a. I poenta nije u tome da je za pisanje web sučelja potrebno mnogo vremena, već je stvar u arhitektonskim karakteristikama freepbx. Pristupi i metode arhitekture freepbx je bio postavljen u vrijeme php4, a u tom trenutku je već postojao php5.6 na kojem je sve moglo biti jednostavnije i praktičnije.

Kap koja je prelila čašu bili su grafički dijagrami u obliku dijagrama. Kada sam pokušao da napravim nešto ovako za freepbx, shvatio sam da ću to morati značajno prepisati i da će biti lakše izgraditi nešto novo.

Ključni zahtjevi su bili:

  • jednostavno podešavanje, intuitivno dostupno čak i administratoru početniku. Dakle, kompanije ne zahtijevaju održavanje PBX-a na našoj strani,
  • laka modifikacija tako da se zadaci rješavaju u odgovarajućem vremenu,
  • jednostavnost integracije sa PBX-om. U freepbx nije postojao API za promjenu postavki, tj. Ne možete, na primjer, kreirati grupe ili glasovne menije iz aplikacije treće strane, već samo iz samog API-ja Asterisk,
  • opensource - za programere je ovo izuzetno važno za modifikacije za klijenta.

Ideja bržeg razvoja je bila da se sva funkcionalnost sastoji od modula u obliku objekata. Svi objekti su morali imati zajedničku roditeljsku klasu, što znači da su imena svih glavnih funkcija već poznata i stoga već postoje zadane implementacije. Objekti će vam omogućiti da dramatično smanjite broj argumenata u obliku asocijativnih nizova sa string ključevima, što možete saznati u freepbx To je bilo moguće ispitivanjem cijele funkcije i ugniježđenih funkcija. U slučaju objekata, banalno autodovršavanje će pokazati sva svojstva, i općenito će pojednostaviti život višestruko. Osim toga, nasljeđivanje i redefiniranje već rješavaju mnoge probleme s modifikacijama.

Sljedeća stvar koja je usporila vrijeme prerade i koja je vrijedila izbjegavati je dupliranje. Ako postoji modul odgovoran za pozivanje zaposlenika, onda bi svi ostali moduli koji trebaju poslati poziv zaposleniku trebali ga koristiti, a ne kreirati vlastite kopije. Dakle, ako treba nešto da promenite, onda ćete morati da promenite samo na jednom mestu i potragu za „kako to funkcioniše“ treba da se vrši na jednom mestu, a ne da se traži kroz ceo projekat.

Prva verzija i prve greške

Prvi prototip bio je spreman za godinu dana. Cijela PBX je, kako je planirano, bila modularna, a moduli su mogli ne samo dodati nove funkcionalnosti za obradu poziva, već i promijeniti sam web interfejs.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php
Da, ideja da napravim dijalplan u obliku takve šeme nije moja, ali je vrlo zgodna i isto sam učinio za Asterisk.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Pisanjem modula, programeri su već mogli:

  • kreirajte vlastitu funkcionalnost za obradu poziva, koja se može postaviti na dijagram, kao iu meni elemenata na lijevoj strani,
  • kreirajte vlastite stranice za web sučelje i dodajte svoje šablone postojećim stranicama (ako je programer stranice to omogućio),
  • dodajte svoje postavke na glavnu karticu postavki ili kreirajte svoju karticu postavki,
  • programer može naslijediti postojeći modul, promijeniti dio funkcionalnosti i registrirati ga pod novim imenom ili zamijeniti originalni modul.

Na primjer, ovako možete kreirati vlastiti glasovni meni:

......
class CPBX_MYIVR extends CPBX_IVR
{
 function __construct()
 {
 parent::__construct();
 $this->_module = "myivr";
 }
}
.....
$myIvrModule = new CPBX_MYIVR();
CPBXEngine::getInstance()->registerModule($myIvrModule,__DIR__); //Зарегистрировать новый модуль
CPBXEngine::getInstance()->registerModuleExtension($myIvrModule,'ivr',__DIR__); //Подменить существующий модуль

Prve složene implementacije donijele su prvi ponos i prva razočaranja. Bilo mi je drago što radi, što sam već mogao da reprodukujem glavne karakteristike freepbx. Bilo mi je drago što se ljudima dopala ideja o šemi. Bilo je još mnogo opcija za pojednostavljenje razvoja, ali čak i u to vrijeme neki od zadataka su već bili olakšani.

API za promjenu konfiguracije PBX-a bio je razočaranje - rezultat uopće nije bio onakav kakav smo željeli. Uzeo sam isti princip kao u freepbx, klikom na dugme Primijeni, cijela konfiguracija se ponovo kreira i moduli se ponovo pokreću.

To izgleda ovako:

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php
*Dialplan je pravilo (algoritam) po kojem se poziv obrađuje.

Ali sa ovom opcijom, nemoguće je napisati normalan API za promjenu postavki PBX-a. Prvo, operacija primjene promjena na Asterisk predugo i zahtijeva puno resursa.
Drugo, ne možete pozvati dvije funkcije u isto vrijeme, jer oba će kreirati konfiguraciju.
Treće, primjenjuje sve postavke, uključujući i one koje je napravio administrator.

U ovoj verziji, kao u Askozia, bilo je moguće generirati konfiguraciju samo promijenjenih modula i ponovo pokrenuti samo potrebne module, ali to su sve polovične mjere. Bilo je potrebno promijeniti pristup.

Druga verzija. Nos izvučen rep zaglavio

Ideja da se riješi problem nije bila ponovno kreiranje konfiguracije i plana biranja Asterisk, ali sačuvajte informacije u bazi podataka i čitajte ih direktno iz baze podataka tokom obrade poziva. Asterisk Već sam znao čitati konfiguracije iz baze podataka, samo promijenite vrijednost u bazi i sljedeći poziv će biti obrađen uzimajući u obzir promjene, a funkcija je bila savršena za čitanje parametara dialplan-a REALTIME_HASH.

Na kraju, nije bilo potrebe ni za ponovnim pokretanjem Asterisk prilikom promjene postavki i sve postavke su se odmah počele primjenjivati ​​na Asterisk.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Jedine promjene u planu biranja su dodavanje brojeva lokala i nagoveštaji. Ali to su bile male promjene

exten=>101,1,GoSub(‘sub-callusers’,s,1(1)); - точечное изменение, добавляется/изменяется через ami

; sub-callusers – универсальная функция генерится при установке модуля.
[sub-callusers]
exten =>s,1,Noop()
exten =>s,n,Set(LOCAL(TOUSERID)=${ARG1})
exten =>s,n,ClearHash(TOUSERPARAM)
exten =>s,n,Set(HASH(TOUSERPARAM)=${REALTIME_HASH(rl_users,id,${LOCAL(TOUSERID)})})
exten =>s,n,GotoIf($["${HASH(TOUSERPARAM,id)}"=""]?return)
...

Možete jednostavno dodati ili promijeniti liniju u planu biranja koristeći Ami (kontrolno sučelje Asterisk) i nije potrebno ponovno pokretanje cijelog plana biranja.

Time je riješen problem s konfiguracijskim API-jem. Možete čak i direktno otići u bazu podataka i dodati novu grupu ili promijeniti, na primjer, vrijeme dial-up-a u polju "vrijeme biranja" za grupu i sljedeći poziv bi već trajao određeno vrijeme (ovo nije preporuka za radnju, jer neke API operacije zahtijevaju Ami pozive).

Prve teške implementacije opet su donijele prvi ponos i razočaranje. Bilo mi je drago što je uspjelo. Baza podataka je postala kritična karika, ovisnost o disku se povećala, bilo je više rizika, ali sve je radilo stabilno i bez problema. I što je najvažnije, sada je sve što je moglo da se uradi preko web interfejsa moglo da se uradi preko API-ja, a korišćene su iste metode. Dodatno, web sučelje se riješilo dugmeta "primijeni postavke na PBX", na koje su administratori često zaboravljali.

Razočarenje je bilo to što je razvoj postao komplikovaniji. Od prve verzije, PHP jezik je generisao plan biranja u jeziku Asterisk i izgleda potpuno nečitljivo, plus sam jezik Asterisk za pisanje dijalplana je izuzetno primitivan.

Kako je to izgledalo:

$usersInitSection = $dialplan->createExtSection('usersinit-sub','s');
$usersInitSection
 ->add('',new Dialplanext_gotoif('$["${G_USERINIT}"="1"]','exit'))
 ->add('',new Dialplanext_set('G_USERINIT','1'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnAnswerSub','usersconnected-sub'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnPredoDialSub','usersinitondial-sub'))
 ->add('',new Dialplanext_set('LOCAL(TECH)','${CUT(CHANNEL(name),/,1)}'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="SIP"]','sipdev'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="PJSIP"]','pjsipdev'))

U drugoj verziji, dijalplan je postao univerzalan, uključivao je sve moguće opcije obrade ovisno o parametrima i njegova veličina se značajno povećala. Sve je to uvelike usporilo vrijeme razvoja, a rastužila me je i sama pomisao da je još jednom potrebno ometati dijalplan.

Treća verzija

Ideja za rješavanje problema nije bila generiranje Asterisk dialplan iz php-a i koristite FastAGI i napišite sva pravila obrade u samom PHP-u. FastAGI dozvoljava Asterisk, da obradite poziv, povežite se na utičnicu. Primajte komande odatle i šaljite rezultate. Dakle, logika dijalplana je već izvan granica Asterisk i može se napisati na bilo kom jeziku, u mom slučaju u PHP-u.

Bilo je mnogo pokušaja i grešaka. Glavni problem je bio što sam već imao puno klasa/fajlova. Bilo je potrebno oko 1,5 sekunde da se naprave objekti, inicijaliziraju i međusobno registruju, a ovo kašnjenje po pozivu nije nešto što se može zanemariti.

Inicijalizacija se trebala dogoditi samo jednom i stoga je potraga za rješenjem počela pisanjem servisa u php-u Pthreads. Nakon tjedan dana eksperimentiranja, ova opcija je odložena zbog zamršenosti načina na koji ovo proširenje funkcionira. Nakon mjesec dana testiranja, morao sam napustiti i asinhrono programiranje u PHP-u; trebalo mi je nešto jednostavno, poznato svakom PHP početniku, a mnoga proširenja za PHP su sinhrona.

Rješenje je bio naš vlastiti višenitni servis u C-u, koji je kompajliran PHPLIB. Učitava sve ATS php fajlove, čeka da se svi moduli inicijaliziraju, dodaje jedan drugom povratni poziv i kada je sve spremno, kešira ga. Prilikom upita od strane FastAGI kreira se stream, u njemu se reproducira kopija iz keša svih klasa i podataka, a zahtjev se prosljeđuje php funkciji.

Uz ovo rješenje, vrijeme od slanja poziva našem servisu do prve komande Asterisk smanjeno sa 1,5s na 0,05s i ovo vrijeme neznatno ovisi o veličini projekta.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Kao rezultat toga, vrijeme za razvoj dijalplana je značajno smanjeno, i to mogu cijeniti jer sam morao da prepišem cijeli dijalplan svih modula u PHP-u. Prvo, metode bi već trebale biti napisane u php-u za dobijanje objekta iz baze podataka; bile su potrebne za prikaz u web sučelju, a drugo, a ovo je glavna stvar, konačno je moguće pogodno raditi sa stringovima sa brojevima i nizovima sa bazom podataka plus mnogo PHP ekstenzija.

Da biste obradili plan biranja u klasi modula, morate implementirati funkciju dialplanDynamicCall i argument pbxCallRequest će sadržavati objekt za interakciju Asterisk.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Osim toga, postalo je moguće otkloniti greške u dijalplanu (php ima xdebug i radi za našu uslugu), možete se kretati korak po korak gledajući vrijednosti varijabli.

Podaci o pozivima

Svaka analitika i izvještaji zahtijevaju ispravno prikupljene podatke, a i ovaj blok PBX-a prošao je dosta pokušaja i grešaka od prve do treće verzije. Često su podaci o pozivima znak. Jedan poziv = jedan snimak: ko je zvao, ko se javio, koliko dugo su razgovarali. U zanimljivijim opcijama postoji dodatni znak koji pokazuje koji je zaposlenik PBX-a pozvan tokom poziva. Ali sve ovo pokriva samo dio potreba.

Početni zahtjevi su bili:

  • sačuvajte ne samo koga je PBX zvala, već i ko se javio, jer ima presretanja i to će se morati uzeti u obzir prilikom analize poziva,
  • vrijeme prije povezivanja sa zaposlenim. U freepbx i neke druge PBX, poziv se smatra odgovornim čim PBX podigne slušalicu. Ali za glasovni meni već morate da podignete slušalicu, tako da se na sve pozive odgovara i vreme čekanja na odgovor postaje 0-1 sekunda. Stoga je odlučeno da se uštedi ne samo vrijeme prije odgovora, već i vrijeme prije povezivanja sa ključnim modulima (modul sam postavlja ovu zastavicu. Trenutno je to “Zaposleni”, “Spoljna linija”),
  • za složeniji plan biranja, kada poziv putuje između različitih grupa, bilo je neophodno da se može ispitati svaki element posebno.

Pokazalo se da je najbolja opcija kada PBX moduli šalju informacije o sebi na pozive i na kraju spremaju informacije u obliku stabla.

Izgleda ovako:

Prvo, opće informacije o pozivu (kao i svi ostali - ništa posebno).

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

  1. Primljen poziv na spoljnoj liniji "Za testiranje"u 05:55:52 sa broja 89295671458 na broj 89999999999, na kraju se javila uposlenica"sekretar2» sa brojem 104. Klijent je čekao 60 sekundi i govorio 36 sekundi.
  2. Zaposlenik"sekretar2"pozove 112 i zaposlenik se javi"Menadžer1» nakon 8 sekundi. Razgovaraju 14 sekundi.
  3. Klijent se prenosi na Zaposlenog"menadžer1“ gdje nastavljaju razgovor još 13 sekundi

Ali ovo je vrh ledenog brega; za svaki zapis možete dobiti detaljnu historiju poziva putem PBX-a.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziranu na Asterisk i Php

Sve informacije su predstavljene kao gniježđenje poziva:

  1. Primljen poziv na spoljnoj liniji "Za testiranje» u 05:55:52 sa broja 89295671458 na broj 89999999999.
  2. U 05:55:53 vanjska linija šalje poziv dolaznom krugu "test»
  3. Prilikom obrade poziva prema šemi, modul “poziv menadžera“, u kojem poziv traje 16 sekundi. Ovo je modul razvijen za klijenta.
  4. Modul "poziv menadžera" šalje poziv službeniku odgovornom za broj (klijentu) "Menadžer1” i čeka 5 sekundi na odgovor. Menadžer nije odgovorio.
  5. Modul "poziv menadžera"šalje poziv grupi"CORP menadžeri" Ovo su drugi menadžeri istog smjera (sjede u istoj prostoriji) i čekaju 11 sekundi na odgovor.
  6. Grupa "CORP menadžeri"poziva zaposlene"Menadžer1, Menadžer2, Menadžer3"istovremeno 11 sekundi. Nema odgovora.
  7. Poziv menadžera se završava. I krug šalje poziv modulu "Odabir rute od 1c" Također modul napisan za klijenta. Ovdje je poziv obrađen 0 sekundi.
  8. Kolo šalje poziv glasovnom meniju "Osnovni sa dodatnim biranjem" Klijent je tamo čekao 31 sekundu, nije bilo dodatnog biranja.
  9. Shema šalje poziv grupi "Sekretarice“, gdje je klijent čekao 12 sekundi.
  10. U grupi se pozivaju 2 zaposlena u isto vrijeme"sekretar1"I"sekretar2" i nakon 12 sekundi zaposlenik odgovara "sekretar2" Odgovor na poziv se duplira u roditeljske pozive. Ispostavilo se da je u grupi odgovorio “sekretar2", prilikom poziva krug je odgovorio "sekretar2" i odgovorio na poziv na vanjskoj liniji sa "sekretar2".

Upravo će čuvanje informacija o svakoj operaciji i njihovo ugniježđenje omogućiti jednostavno pravljenje izvještaja. Izvještaj na glasovnom meniju će vam pomoći da saznate koliko pomaže ili ometa. Izradite izvještaj o propuštenim pozivima od strane zaposlenih, vodeći računa da je poziv presretnut i da se stoga ne smatra propuštenim, te da se radi o grupnom pozivu, a da se neko drugi javio ranije, što znači da poziv također nije propušten.

Takvo skladištenje informacija će vam omogućiti da svaku grupu uzmete zasebno i utvrdite koliko efikasno radi, te da napravite grafikon odgovornih i propuštenih grupa po satu. Koliko je precizna veza sa odgovornim menadžerom možete provjeriti i analizom transfera nakon povezivanja sa menadžerom.

Možete provesti i prilično netipične studije, na primjer, koliko često brojevi koji nisu u bazi podataka biraju ispravan lokal ili koji postotak odlaznih poziva se prosljeđuje na mobilni telefon.

Šta je na kraju?

Za održavanje PBX-a nije potreban stručnjak, to može učiniti i najobičniji administrator - testirano u praksi.

Za modifikacije nisu potrebni stručnjaci sa ozbiljnim kvalifikacijama, dovoljno je poznavanje PHP-a, jer Moduli su već napisani i za SIP protokol, i za red čekanja, i za pozivanje službenika i ostalo. Postoji klasa omotača za Asterisk. Da bi razvio modul, programer može (i na dobar način bi trebao) pozvati gotove module. I znanje Asterisk potpuno su nepotrebni ako klijent traži da se doda stranica sa nekim novim izvještajem. Ali praksa pokazuje da iako se programeri trećih strana mogu snaći, osjećaju se nesigurno bez dokumentacije i normalnog pokrivanja komentara, tako da još uvijek ima prostora za poboljšanje.

Moduli mogu:

  • kreirati nove mogućnosti obrade poziva,
  • dodajte nove blokove u web sučelje,
  • naslijediti bilo koji od postojećih modula, redefinirati funkcije i zamijeniti ih ili jednostavno biti malo izmijenjena kopija,
  • dodajte svoje postavke u predložak postavki drugih modula i još mnogo toga.

PBX podešavanja preko API-ja. Kao što je gore opisano, sva podešavanja se pohranjuju u bazu podataka i čitaju u trenutku poziva, tako da možete promijeniti sve postavke PBX-a putem API-ja. Prilikom pozivanja API-ja, konfiguracija se ne kreira ponovo i moduli se ne pokreću, stoga nije bitno koliko postavki i zaposlenih imate. API zahtjevi se izvršavaju brzo i ne blokiraju jedni druge.

PBX pohranjuje sve ključne operacije sa pozivima sa trajanjem (čekanje/razgovor), ugnježđenjem i u terminima PBX (zaposleni, grupa, eksterna linija, a ne kanal, broj). Ovo vam omogućava da napravite različite izvještaje za određene klijente, a većina posla je kreiranje korisničkog sučelja.

Vrijeme će pokazati šta će se dalje dogoditi. Ima još mnogo nijansi koje treba preraditi, ima još mnogo planova, ali je prošlo godinu dana od kreiranja 3. verzije i već sada možemo reći da ideja radi. Glavni nedostatak verzije 3 su hardverski resursi, ali to je obično ono što morate platiti radi lakšeg razvoja.

izvor: www.habr.com

Dodajte komentar