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

Sigurno je mnogima od vas, poput mene, pala na pamet ideja napraviti nešto jedinstveno. U ovom ću članku opisati tehničke probleme i rješenja s kojima sam se morao suočiti pri razvoju PBX-a. Možda to nekome pomogne da se odluči za vlastitu ideju, a nekome da krene utabanim putem, jer i meni su dobro došla iskustva pionira.

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

Ideja i ključni zahtjevi

A sve je počelo jednostavno iz ljubavi prema Zvjezdica (okvir za izgradnju komunikacijskih aplikacija), automatizacija telefonije i instalacija freepbx (web sučelje za Zvjezdica). Ako su potrebe tvrtke bile bez specifičnosti i spadale u mogućnosti freepbx - sve je odlično. Cijela instalacija obavljena je u roku od XNUMX sata, tvrtka je dobila konfiguriranu telefonsku centralu, korisničko sučelje i kratku obuku te podršku po želji.

Ali najzanimljiviji zadaci bili su nestandardni i tada nije bilo tako bajno. Zvjezdica može učiniti mnogo, ali da bi web sučelje održalo u ispravnom stanju, bilo je potrebno potrošiti višestruko više vremena. Tako bi mali detalj mogao potrajati mnogo dulje od instaliranja ostatka PBX-a. I nije stvar u tome da treba dugo vremena da se napiše web sučelje, već je stvar u arhitektonskim značajkama freepbx. Arhitektonski pristupi i metode freepbx postavljen je u vrijeme php4, au tom trenutku već je postojao php5.6 na kojem se sve moglo učiniti jednostavnijim i praktičnijim.

Kap koja je prelila čašu bili su grafički dialplanovi u obliku dijagrama. Kad sam pokušao izgraditi nešto ovakvo za freepbx, shvatio sam da ću ga morati značajno prepisati i lakše ću izgraditi nešto novo.

Ključni zahtjevi bili su:

  • jednostavno postavljanje, intuitivno dostupno čak i administratoru početniku. Stoga tvrtke ne zahtijevaju održavanje PBX-a s naše strane,
  • laka modifikacija kako bi se zadaci riješili u odgovarajućem vremenu,
  • jednostavnost integracije s PBX-om. U freepbx nije postojao API za promjenu postavki, tj. Ne možete, na primjer, stvoriti grupe ili glasovne izbornike iz aplikacije treće strane, samo iz samog API-ja Zvjezdica,
  • opensource - za programere ovo je iznimno važno za izmjene za klijenta.

Ideja bržeg razvoja bila je da se sva funkcionalnost sastoji od modula u obliku objekata. Svi objekti morali su 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 dramatično smanjenje broja argumenata u obliku asocijativnih nizova s ​​ključevima niza, što možete pronaći u freepbx To je bilo moguće ispitivanjem cijele funkcije i ugniježđenih funkcija. U slučaju objekata, banalno automatsko dovršavanje će pokazati sva svojstva i općenito će višestruko pojednostaviti život. Osim toga, nasljeđivanje i redefinicija već rješavaju mnoge probleme s izmjenama.

Sljedeća stvar koja je usporila vrijeme prerade i koju je vrijedilo izbjegavati bilo je dupliciranje. Ako postoji modul odgovoran za biranje zaposlenika, tada bi svi ostali moduli koji trebaju poslati poziv zaposleniku trebali koristiti njega, a ne stvarati vlastite kopije. Dakle, ako trebate nešto promijeniti, onda ćete morati promijeniti samo na jednom mjestu i potragu za “kako to radi” treba provesti na jednom mjestu, a ne tražiti kroz cijeli projekt.

Prva verzija i prve greške

Prvi prototip bio je spreman za godinu dana. Cijeli PBX, kako je planirano, bio je modularan, a moduli su mogli ne samo dodati nove funkcionalnosti za obradu poziva, već i promijeniti samo web sučelje.

Priča o jednom projektu ili kako sam proveo 7 godina stvarajući PBX baziran na Asterisk i Php
Da, ideja o izgradnji dialplana u obliku takve sheme nije moja, ali je vrlo zgodna i učinio sam isto za Zvjezdica.

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

Pišući modul, programeri su već mogli:

  • kreirati vlastitu funkcionalnost za obradu poziva, koja se može smjestiti na dijagram, kao iu izbornik elemenata s lijeve strane,
  • izradite vlastite stranice za web sučelje i dodajte svoje predloške na postojeće stranice (ako je razvojni programer stranice to omogućio),
  • dodajte svoje postavke na glavnu karticu postavki ili izradite vlastitu 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 izbornik:

......
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 je uspjelo, što sam već uspio reproducirati glavne značajke freepbx. Bilo mi je drago što se ljudima svidjela ideja sheme. Bilo je još mnogo opcija za pojednostavljenje razvoja, ali čak iu to vrijeme neki su zadaci već bili olakšani.

API za promjenu PBX konfiguracije bio je razočaranje - rezultat uopće nije bio onakav kakav smo željeli. Ja sam uzeo isti princip kao u freepbx, klikom na gumb Primijeni ponovno se stvara cijela konfiguracija i ponovno se pokreću moduli.

Izgleda ovako:

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

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

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

Druga verzija. Nos izvučen rep zapeo

Ideja za rješavanje problema nije bila ponovno stvaranje konfiguracije i plana biranja za Zvjezdica, ali sprema informacije u bazu podataka i čita iz baze podataka izravno tijekom obrade poziva. Zvjezdica Već sam znao čitati konfiguracije iz baze, 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 dialplana REALTIME_HASH.

Na kraju nije bilo potrebe ni za restartom Zvjezdica prilikom promjene postavki i sve su se postavke odmah počele primjenjivati ​​na Zvjezdica.

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

Jedine promjene plana biranja su dodavanje internih brojeva i savjeti. Ali to su bile sitne 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 pomoću Ami (kontrolno sučelje Zvjezdica) i nije potrebno ponovno pokretanje cijelog plana biranja.

Ovo je riješilo problem s konfiguracijskim API-jem. Možete čak i izravno otići u bazu podataka i dodati novu grupu ili promijeniti, na primjer, vrijeme biranja u polju "vrijeme biranja" za grupu i sljedeći poziv bi već trajao navedeno vrijeme (Ovo nije preporuka za jer neke API operacije zahtijevaju Ami poziva).

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

Razočaranje je bilo to što se razvoj zakomplicirao. Od prve verzije, PHP jezik je generirao dialplan u jeziku Zvjezdica i izgleda potpuno nečitljivo, plus sam jezik Zvjezdica za pisanje plana biranja krajnje je primitivno.

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 dialplan je postao univerzalan, uključivao je sve moguće mogućnosti obrade ovisno o parametrima i njegova veličina se značajno povećala. Sve je to jako usporilo vrijeme razvoja, a sama pomisao da je opet potrebno zadirati u dialplan me je rastužila.

Treća verzija

Ideja za rješavanje problema nije bila generirati Zvjezdica dialplan iz php-a i koristite FastAGI i napišite sva pravila obrade u samom PHP-u. FastAGI to omogućuje Zvjezdica, za obradu poziva spojite se na utičnicu. Primajte naredbe od tamo i šaljite rezultate. Stoga je logika dialplana već izvan granica Zvjezdica i može se napisati na bilo kojem jeziku, u mom slučaju u PHP-u.

Bilo je puno pokušaja i pogrešaka. Glavni problem je bio što sam već imao mnogo klasa/datoteka. Bilo je potrebno oko 1,5 sekunde za stvaranje objekata, njihovo inicijaliziranje i međusobno registriranje, 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 započela pisanjem usluge u php-u pomoću Pthreads. Nakon tjedan dana eksperimentiranja, ova je opcija odložena zbog zamršenosti rada ovog proširenja. Nakon mjesec dana testiranja, također sam morao napustiti asinkrono programiranje u PHP-u; trebalo mi je nešto jednostavno, poznato svakom PHP početniku, a mnoga proširenja za PHP su sinkrona.

Rješenje je bila naša vlastita višenitna usluga u C-u, s kojom smo kompajlirani PHPLIB. Učitava sve ATS php datoteke, čeka da se svi moduli inicijaliziraju, dodaje povratni poziv jedan drugome i kada je sve spremno, sprema ga u predmemoriju. Prilikom upita od strane FastAGI kreira se stream, u njemu se reproducira kopija iz predmemorije svih klasa i podataka te se zahtjev prosljeđuje php funkciji.

Ovim rješenjem vrijeme od slanja poziva našem servisu do prve naredbe Zvjezdica smanjeno s 1,5 s na 0,05 s i ovo vrijeme malo ovisi o veličini projekta.

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

Kao rezultat toga, vrijeme za razvoj dialplana značajno je smanjeno, a ja to mogu cijeniti jer sam morao ponovno napisati cijeli dialplan svih modula u PHP-u. Prvo, metode bi već trebale biti napisane u php-u za dobivanje objekta iz baze podataka; bile su potrebne za prikaz u web sučelju, i drugo, i to je glavna stvar, konačno je moguće prikladno raditi s nizovima s brojevima i nizovima s bazom podataka i mnogim PHP ekstenzijama.

Za obradu plana biranja u klasi modula trebate implementirati funkciju dialplanDynamicCall i argument pbxCallRequest sadržavat će objekt za interakciju Zvjezdica.

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

Osim toga, postalo je moguće ispraviti pogreške u dialplanu (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šća zahtijevaju ispravno prikupljene podatke, a ovaj PBX blok također je prošao kroz dosta pokušaja i pogrešaka od prve do treće verzije. Često su podaci o pozivu znak. Jedan poziv = jedna snimka: tko je zvao, tko se javio, koliko su dugo razgovarali. U zanimljivijim opcijama postoji dodatni znak koji pokazuje koji je zaposlenik PBX-a pozvan tijekom poziva. Ali sve to pokriva samo dio potreba.

Početni zahtjevi bili su:

  • spasiti ne samo koga je PBX nazvao, već i tko je odgovorio, jer ima presretanja i to će se morati uzeti u obzir pri analizi poziva,
  • vremena prije povezivanja sa zaposlenikom. U freepbx i nekim drugim PBX uređajima, poziv se smatra primljenim čim PBX prihvati slušalicu. Ali za glasovni izbornik već morate podići slušalicu, tako da se na sve pozive odgovara, a vrijeme čekanja na odgovor postaje 0-1 sekunda. Stoga je odlučeno uštedjeti ne samo vrijeme prije odgovora, već i vrijeme prije povezivanja s ključnim modulima (sam modul postavlja ovu zastavicu. Trenutno je to “Zaposlenik”, “Vanjska linija”),
  • za složeniji plan biranja, kada poziv putuje između različitih grupa, bilo je potrebno moći ispitati svaki element zasebno.

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

Izgleda ovako:

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

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

  1. Primljen poziv na vanjskoj liniji "Za test"u 05:55:52 sa broja 89295671458 na broj 89999999999 na kraju se javila djelatnica"Tajnik2» s brojem 104. Klijent je čekao 60 sekundi i govorio 36 sekundi.
  2. Zaposlenik "Tajnik2"nazove 112 i javi se djelatnik"Upravitelj1» nakon 8 sekundi. Razgovaraju 14 sekundi.
  3. Klijent se prenosi na Zaposlenika "upravitelj1" gdje nastavljaju pričati još 13 sekundi

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

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

Sve informacije predstavljene su kao gniježđenje poziva:

  1. Primljen poziv na vanjskoj liniji "Za test» 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 shemi, modul “poziv menadžera“, u kojem je poziv 16 sekundi. Ovo je modul razvijen za klijenta.
  4. Modul "poziv menadžera" šalje poziv djelatniku odgovornom za broj (klijent) "Upravitelj1” i čeka 5 sekundi za odgovor. Upravitelj nije odgovorio.
  5. Modul "poziv menadžera"šalje poziv grupi"menadžeri CORP-a" Ovo su drugi upravitelji istog smjera (sjede u istoj prostoriji) i čekaju 11 sekundi na odgovor.
  6. Grupa "menadžeri CORP-a"poziva zaposlenike"Upravitelj1, Upravitelj2, Upravitelj3"istovremeno 11 sekundi. Nema odgovora.
  7. Voditeljev poziv završava. I krug šalje poziv modulu "Odabir rute iz 1c" Također modul napisan za klijenta. Ovdje je poziv obrađen 0 sekundi.
  8. Krug šalje poziv glasovnom izborniku "Osnovni s dodatnim biranjem" Klijent je tamo čekao 31 sekundu, nije bilo dodatnog biranja.
  9. Shema šalje poziv grupi "Tajnice“, gdje je klijent čekao 12 sekundi.
  10. U grupi su pozvana 2 zaposlenika u isto vrijeme "Tajnik1"A"Tajnik2" i nakon 12 sekundi zaposlenik odgovara "Tajnik2" Odgovor na poziv se duplicira u nadređene pozive. Ispostavilo se da je u grupi odgovorio "Tajnik2", prilikom poziva krug je odgovorio "Tajnik2" i odgovorio na poziv na vanjskoj liniji s "Tajnik2".

Spremanje podataka o svakoj operaciji i njihovo ugniježđivanje omogućit će jednostavno izradu izvješća. Izvještaj o glasovnom izborniku pomoći će vam da saznate koliko on pomaže ili odmaže. Izraditi izvješće o propuštenim pozivima zaposlenika, uzimajući u obzir da je poziv presretnut i stoga se ne smatra propuštenim, te uzimajući u obzir da se radi o grupnom pozivu, te da je netko drugi ranije odgovorio, što znači da poziv također nije propušten.

Takvo pohranjivanje informacija omogućit će vam da svaku grupu zasebno uzmete i odredite koliko učinkovito radi, te izgradite grafikon grupa na koje je odgovoreno i propuštenih po satu. Također možete provjeriti koliko je veza s odgovornim upraviteljem točna analizom prijenosa nakon povezivanja s upraviteljem.

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

Rezultat?

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

Za izmjene nisu potrebni stručnjaci s ozbiljnim kvalifikacijama; dovoljno je poznavanje PHP-a, jer Već su napisani moduli za SIP protokol, i za red čekanja, i za pozivanje zaposlenika, i drugi. Postoji klasa omotača za Zvjezdica. Da bi razvio modul, programer može (i na dobar način bi trebao) pozvati gotove module. I znanje Zvjezdica potpuno su nepotrebni ako klijent traži dodavanje stranice s nekim novim izvješćem. 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š ima prostora za napredak.

Moduli mogu:

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

PBX postavke putem API-ja. Kao što je gore opisano, sve postavke su pohranjene u bazi podataka i čitaju se u trenutku poziva, tako da možete promijeniti sve PBX postavke putem API-ja. Prilikom pozivanja API-ja, konfiguracija se ne kreira ponovno i moduli se ne pokreću ponovno, stoga nije važno koliko postavki i zaposlenika imate. API zahtjevi se izvršavaju brzo i ne blokiraju jedni druge.

PBX pohranjuje sve ključne operacije s pozivima s trajanjem (čekanje/razgovor), gniježđenjem iu terminima PBX-a (zaposlenik, grupa, vanjska linija, ne kanal, broj). To vam omogućuje izradu različitih izvješća za određene klijente, a većina posla je stvaranje korisničkog sučelja.

Vrijeme će pokazati što će biti dalje. Ima još mnogo nijansi koje treba preraditi, još ima mnogo planova, ali prošla je godina dana od stvaranja 3. verzije i već možemo reći da ideja funkcionira. Glavni nedostatak verzije 3 su hardverski resursi, ali to je obično ono što morate platiti za jednostavnost razvoja.

Izvor: www.habr.com

Dodajte komentar