La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Certe multaj el vi, kiel mi, havis ideon fari ion unikan. En ĉi tiu artikolo mi priskribos la teknikajn problemojn kaj solvojn, kiujn mi devis alfronti dum disvolvado de la PBX. Eble tio helpos iun decidi pri sia propra ideo, kaj iun sekvi la tre paŝitan vojon, ĉar ankaŭ mi profitis de la sperto de pioniroj.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Ideo kaj ŝlosilaj postuloj

Kaj ĉio komenciĝis simple per amo por Asterisko (kadro por konstruado de komunikadaplikoj), aŭtomatigo de telefonio kaj instalaĵoj Senpaga PBX (retinterfaco por Asterisko). Se la bezonoj de la kompanio estis sen specifaj kaj ene de la kapabloj Senpaga PBX - ĉio estas bonega. La tuta instalado okazis ene de XNUMX horoj, la kompanio ricevis agordita PBX, uzant-amika interfaco kaj mallonga trejnado plus subteno se dezirite.

Sed la plej interesaj taskoj estis ne-normaj kaj tiam ĝi ne estis tiel fabela. Asterisko povas fari multon, sed por konservi la retinterfacon en funkciado, necesis pasigi multfoje pli da tempo. Do malgranda detalo povus daŭri multe pli longe ol instali la reston de la PBX. Kaj la afero ne estas, ke necesas longa tempo por skribi retan interfacon, sed la afero estas en la arkitekturaj trajtoj. Senpaga PBX. Arkitekturaj aliroj kaj metodoj Senpaga PBX estis aranĝita en la tempo de php4, kaj en tiu momento jam ekzistis php5.6 sur kiu ĉio povus esti pli simpla kaj pli oportuna.

La lasta pajlo estis grafikaj dialplanoj en la formo de diagramo. Kiam mi provis konstrui ion tian por Senpaga PBX, mi rimarkis, ke mi devos grave reverki ĝin kaj estus pli facile konstrui ion novan.

La ĉefaj postuloj estis:

  • simpla agordo, intuicie alirebla eĉ por komencanta administranto. Tiel, kompanioj ne postulas PBX prizorgado de nia flanko,
  • facila modifo por ke taskoj estu solvitaj en taŭga tempo,
  • facileco de integriĝo kun PBX. U Senpaga PBX ekzistis neniu API por ŝanĝi agordojn, t.e. Vi ne povas, ekzemple, krei grupojn aŭ voĉajn menuojn de triaparta aplikaĵo, nur la API mem Asterisko,
  • malfermfonteco - por programistoj tio estas ege grava por modifoj por la kliento.

La ideo de pli rapida disvolviĝo estis, ke ĉiuj funkcioj konsistas el moduloj en formo de objektoj. Ĉiuj objektoj devis havi komunan gepatran klason, kio signifas, ke la nomoj de ĉiuj ĉefaj funkcioj jam estas konataj kaj tial ekzistas jam defaŭltaj efektivigoj. Objektoj permesos al vi draste redukti la nombron da argumentoj en formo de asociaj tabeloj kun ŝnuraj klavoj, kiujn vi povas ekscii en Senpaga PBX Eblis ekzamenante la tutan funkcion kaj nestitajn funkciojn. En la kazo de objektoj, banala aŭtokompleto montros ĉiujn ecojn, kaj ĝenerale multfoje simpligos la vivon. Krome, heredo kaj redifino jam solvas multajn problemojn kun modifoj.

La sekva afero, kiu malrapidigis la relaboran tempon kaj estis evitinda, estis duobligo. Se ekzistas modulo respondeca pri diskado de dungito, tiam ĉiuj aliaj moduloj, kiuj bezonas sendi vokon al dungito, devas uzi ĝin, kaj ne krei siajn proprajn kopiojn. Do, se vi bezonas ŝanĝi ion, tiam vi devos ŝanĝi nur en unu loko kaj la serĉo pri "kiel ĝi funkcias" devas esti farita en unu loko, kaj ne serĉita tra la tuta projekto.

Unua versio kaj unuaj eraroj

La unua prototipo estis preta ene de jaro. La tuta PBX, kiel planite, estis modula, kaj la moduloj povis ne nur aldoni novan funkciecon por prilaborado de vokoj, sed ankaŭ ŝanĝi la retinterfacon mem.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php
Jes, la ideo konstrui dialplanon en la formo de tia skemo ne estas mia, sed ĝi estas tre oportuna kaj mi faris la samon por Asterisko.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Skribante modulon, programistoj jam povus:

  • kreu vian propran funkcion por voka prilaborado, kiu povus esti metita sur la diagramon, same kiel en la menuo de elementoj maldekstre,
  • kreu viajn proprajn paĝojn por la TTT-interfaco kaj aldonu viajn ŝablonojn al ekzistantaj paĝoj (se la paĝprogramisto provizis tion),
  • aldonu viajn agordojn al la ĉefa agorda langeto aŭ kreu vian propran agorda langeto,
  • la programisto povas heredi de ekzistanta modulo, ŝanĝi parton de la funkcieco kaj registri ĝin sub nova nomo aŭ anstataŭigi la originalan modulon.

Ekzemple, jen kiel vi povas krei vian propran voĉan menuon:

......
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__); //Подменить существующий модуль

La unuaj kompleksaj efektivigoj alportis la unuan fieron kaj la unuajn seniluziiĝojn. Mi ĝojis, ke ĝi funkciis, ke mi jam povis reprodukti la ĉefajn trajtojn Senpaga PBX. Mi ĝojis, ke homoj ŝatis la ideon de la skemo. Ankoraŭ estis multaj ebloj por simpligi evoluon, sed eĉ tiam iuj el la taskoj jam estis plifaciligitaj.

La API por ŝanĝi la PBX-agordon estis seniluziiĝo - la rezulto tute ne estis tio, kion ni volis. Mi prenis la saman principon kiel en Senpaga PBX, alklakante la butonon Apliki, la tuta agordo estas rekreita kaj la moduloj estas rekomencitaj.

Ĝi aspektas jene:

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php
*Dialplano estas regulo (algoritmo) per kiu voko estas procesita.

Sed kun ĉi tiu opcio, estas neeble skribi normalan API por ŝanĝi la PBX-agordojn. Unue, la operacio apliki ŝanĝojn al Asterisko tro longa kaj rimedo-intensa.
Due, vi ne povas nomi du funkciojn samtempe, ĉar ambaŭ kreos la agordon.
Trie, ĝi aplikas ĉiujn agordojn, inkluzive de tiuj faritaj de la administranto.

En ĉi tiu versio, kiel en Askozia, eblis generi la agordon de nur ŝanĝitaj moduloj kaj rekomenci nur la necesajn modulojn, sed ĉi tiuj ĉiuj estas duonmezuroj. Necesis ŝanĝi la aliron.

Dua versio. Nazo eltiris voston algluiĝis

La ideo por solvi la problemon estis ne rekrei la agordon kaj telefonplanon por Asterisko, sed konservu informojn al la datumbazo kaj legu el la datumbazo rekte dum prilaborado de la voko. Asterisko Mi jam sciis kiel legi agordojn el la datumbazo, simple ŝanĝi la valoron en la datumbazo kaj la sekva alvoko estos procesita konsiderante la ŝanĝojn, kaj la funkcio estis perfekta por legi dialplan-parametrojn. REALTIME_HASH.

Fine, ne necesis eĉ rekomenci Asterisko kiam ŝanĝante la agordojn kaj ĉiuj agordoj komencis esti aplikata tuj al Asterisko.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

La nuraj ŝanĝoj al la telefonplano estas la aldono de etendaĵoj kaj aludoj. Sed ĉi tiuj estis malgrandaj punktoŝanĝoj

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)
...

Vi povas facile aldoni aŭ ŝanĝi linion en la dialplano uzante kiu (kontrola interfaco Asterisko) kaj neniu rekomenco de la tuta dialplano estas bezonata.

Ĉi tio solvis la problemon kun la agorda API. Vi eĉ povus rekte eniri la datumbazon kaj aldoni novan grupon aŭ ŝanĝi, ekzemple, la telefontempon en la kampo "dialtime" por la grupo kaj la sekva alvoko jam daŭros la specifitan tempon (Ĉi tio ne estas rekomendo por ago, ĉar iuj API-operacioj postulas kiu vokoj).

La unuaj malfacilaj efektivigoj denove alportis la unuan fieron kaj seniluziiĝon. Mi ĝojis, ke ĝi funkciis. La datumbazo fariĝis kritika ligilo, la dependeco de la disko pliiĝis, estis pli da riskoj, sed ĉio funkciis stabile kaj senprobleme. Kaj plej grave, nun ĉio, kio povus esti farita per la retinterfaco, povus esti farita per la API, kaj la samaj metodoj estis uzataj. Aldone, la retinterfaco forigis la butonon "apliki agordojn al PBX", pri kiu administrantoj ofte forgesis.

La seniluziiĝo estis, ke la evoluo fariĝis pli komplika. Ekde la unua versio, la PHP-lingvo generis dialplanon en la lingvo Asterisko kaj ĝi aspektas tute nelegebla, plus la lingvo mem Asterisko por verki dialplanon ĝi estas ege primitiva.

Kiel ĝi aspektis:

$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'))

En la dua versio, la dialplano iĝis universala, ĝi inkludis ĉiujn eblajn pretigajn elektojn depende de la parametroj kaj ĝia grandeco signife pliiĝis. Ĉio ĉi multe malrapidigis la evoluotempon, kaj la penso mem, ke denove necesas enmiksiĝi en la dialplanon, malĝojigis min.

Tria versio

La ideo solvi la problemon estis ne generi Asterisko dialplan de php kaj uzu FastAGI kaj skribu ĉiujn prilaborajn regulojn en PHP mem. FastAGI permesas al Asterisko, por procesi la vokon, konektu al la ingo. Ricevu komandojn de tie kaj sendu rezultojn. Tiel, la logiko de la dialplano jam estas ekster la limoj Asterisko kaj povas esti skribita en ajna lingvo, en mia kazo en PHP.

Estis multe da provo kaj eraro. La ĉefa problemo estis, ke mi jam havis multajn klasojn/dosierojn. Necesis ĉirkaŭ 1,5 sekundoj por krei objektojn, pravalorigi ilin kaj registri unu la alian inter si, kaj ĉi tiu prokrasto por voko ne estas io ignorebla.

Inicialigo devus esti okazinta nur unufoje kaj tial la serĉo de solvo komenciĝis per skribado de servo en php uzante Pfadenoj. Post semajno da eksperimentado, ĉi tiu opcio estis arkivita pro la komplikaĵoj de kiel ĉi tiu etendo funkcias. Post unu monato da testado, mi ankaŭ devis forlasi nesinkronan programadon en PHP; mi bezonis ion simplan, konatan al iu ajn PHP-komencanto, kaj multaj etendoj por PHP estas sinkronaj.

La solvo estis nia propra plurfadena servo en C, kun kiu estis kompilita PHPLIB. Ĝi ŝarĝas ĉiujn ATS php-dosierojn, atendas ke ĉiuj moduloj pravaloriĝos, aldonas revokon unu al la alia, kaj kiam ĉio estas preta, konservas ĝin. Demandante per FastAGI rivereto estas kreita, kopio el la kaŝmemoro de ĉiuj klasoj kaj datumoj estas reproduktita en ĝi, kaj la peto estas pasita al la php-funkcio.

Kun ĉi tiu solvo, la tempo de sendado de voko al nia servo ĝis la unua komando Asterisko malpliiĝis de 1,5s al 0,05s kaj ĉi tiu tempo dependas iomete de la grandeco de la projekto.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Kiel rezulto, la tempo por dialplan-disvolviĝo estis signife reduktita, kaj mi povas aprezi tion ĉar mi devis reverki la tutan dialplanon de ĉiuj moduloj en PHP. Unue, metodoj devus esti jam skribitaj en php por akiri objekton el la datumbazo; ili estis bezonataj por montri en la retinterfaco, kaj due, kaj ĉi tio estas la ĉefa afero, finfine eblas oportune labori kun ĉenoj kun nombroj kaj tabeloj. kun datumbazo plus multaj PHP-etendaĵoj.

Por prilabori la dialplanon en la modula klaso vi devas efektivigi la funkcion dialplanDynamicCall kaj argumento pbxCallRequest enhavos objekton kun kiu interagi Asterisko.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Krome, eblis sencimigi la dialplanon (php havas xdebug kaj ĝi funkcias por nia servo), vi povas movi paŝon post paŝo rigardante la valorojn de variabloj.

Vokaj datumoj

Ajna analizo kaj raportoj postulas ĝuste kolektitajn datumojn, kaj ĉi tiu PBX-bloko ankaŭ trapasis multajn provojn kaj erarojn de la unua ĝis la tria versio. Ofte, vokaj datumoj estas signo. Unu voko = unu registrado: kiu vokis, kiu respondis, kiom longe ili parolis. En pli interesaj opcioj, estas plia signo indikanta kiun PBX-oficisto estis vokita dum la voko. Sed ĉio ĉi kovras nur parton de la bezonoj.

La komencaj postuloj estis:

  • ŝparu ne nur kiun la PBX vokis, sed ankaŭ kiu respondis, ĉar estas interkaptoj kaj ĉi tio devos esti konsiderata kiam oni analizas vokojn,
  • tempon antaŭ konektiĝi kun dungito. En Senpaga PBX kaj iuj aliaj PBXoj, la voko estas konsiderita respondita tuj kiam la PBX prenas la telefonon. Sed por la voĉa menuo vi jam bezonas preni la telefonon, do ĉiuj alvokoj estas responditaj kaj la atendotempo por respondo fariĝas 0-1 sekundo. Tial oni decidis ŝpari ne nur la tempon antaŭ respondo, sed la tempon antaŭ konekti kun ŝlosilaj moduloj (la modulo mem starigas ĉi tiun flagon. Nuntempe ĝi estas "Dungito", "Ekstera linio"),
  • por pli kompleksa dialplano, kiam voko vojaĝas inter malsamaj grupoj, estis necese povi ekzameni ĉiun elementon aparte.

La plej bona opcio rezultis esti kiam la PBX-moduloj sendas informojn pri si mem dum alvokoj kaj finfine konservas la informojn en la formo de arbo.

Ĝi aspektas tiel:

Unue, ĝeneralaj informoj pri la alvoko (kiel ĉiuj aliaj - nenio speciala).

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

  1. Ricevis vokon sur ekstera linio "Por la testo"je 05:55:52 de la numero 89295671458 al la numero 89999999999, finfine respondis oficisto"Sekretario 2» kun numero 104. La kliento atendis 60 sekundojn kaj parolis dum 36 sekundoj.
  2. Dungito "Sekretario 2"vokas al 112 kaj dungito respondas"Administranto 1» post 8 sekundoj. Ili parolas dum 14 sekundoj.
  3. La Kliento estas transdonita al la Dungito "manaĝero1"kie ili daŭre parolas dum pliaj 13 sekundoj

Sed ĉi tio estas la pinto de la glacimonto; por ĉiu rekordo vi povas ricevi detalan alvokon-historion per la PBX.

La rakonto pri unu projekto aŭ kiel mi pasigis 7 jarojn kreante PBX bazitan sur Asterisk kaj Php

Ĉiuj informoj estas prezentitaj kiel nestado de vokoj:

  1. Ricevis vokon sur ekstera linio "Por la testo» je 05:55:52 de la numero 89295671458 al la numero 89999999999.
  2. Je 05:55:53 la ekstera linio sendas vokon al la Envenanta cirkvito "testo»
  3. Kiam vi prilaboras vokon laŭ la skemo, la modulo "alvoko de administranto", en kiu la voko estas 16 sekundoj. Ĉi tio estas modulo evoluigita por la kliento.
  4. Modulo "alvoko de administranto" sendas vokon al la dungito respondeca pri la numero (kliento) "Administranto 1” kaj atendas 5 sekundojn por respondo. La manaĝero ne respondis.
  5. Modulo "alvoko de administranto"sendas vokon al la grupo"CORP-manaĝeroj" Ĉi tiuj estas aliaj administrantoj de la sama direkto (sidantaj en la sama ĉambro) kaj atendante 11 sekundojn por respondo.
  6. Grupo "CORP-manaĝeroj"vokas dungitojn"Administranto 1, Administranto 2, Administranto 3"samtempe dum 11 sekundoj. Neniu Respondo.
  7. La alvoko de la administranto finiĝas. Kaj la cirkvito sendas vokon al la modulo "Elektante itineron el 1c" Ankaŭ modulo skribita por la kliento. Ĉi tie la voko estis procesita dum 0 sekundoj.
  8. La cirkvito sendas vokon al la voĉa menuo "Baza kun plia diskado" La kliento atendis tie dum 31 sekundoj, ne estis plia diskado.
  9. La skemo sendas vokon al la Grupo "Sekretarioj", kie la kliento atendis 12 sekundojn.
  10. En grupo, 2 dungitoj estas vokitaj samtempe "Sekretario 1"Kaj"Sekretario 2"kaj post 12 sekundoj la dungito respondas"Sekretario 2" La respondo al la voko estas duobligita en gepatraj vokoj. Montriĝas, ke en la grupo li respondis "Sekretario 2", dum vokado de la cirkvito respondis "Sekretario 2" kaj respondis la vokon sur la ekstera linio per "Sekretario 2".

Estas la konservado de informoj pri ĉiu operacio kaj ilia nestado, kiu ebligos simple fari raportojn. Raporto pri la voĉa menuo helpos vin ekscii kiom ĝi helpas aŭ malhelpas. Konstruu raporton pri vokoj maltrafitaj de dungitoj, konsiderante ke la voko estis kaptita kaj tial ne estas konsiderata maltrafita, kaj konsiderante ke ĝi estis grupvoko, kaj iu alia respondis pli frue, kio signifas, ke la voko ankaŭ ne estis maltrafita.

Tia konservado de informoj permesos al vi preni ĉiun grupon aparte kaj determini kiom efike ĝi funkcias, kaj konstrui grafeon de responditaj kaj maltrafitaj grupoj laŭhoro. Vi ankaŭ povas kontroli kiom preciza la konekto al la respondeca administranto estas analizante la translokigojn post konekto al la administranto.

Vi ankaŭ povas fari sufiĉe maltipajn studojn, ekzemple, kiom ofte nombroj, kiuj ne estas en la datumbazo, markas la ĝustan etendon aŭ kian procenton de elirantaj vokoj estas plusenditaj al poŝtelefono.

Kio en la fino?

Specialisto ne estas postulata por konservi la PBX; la plej ordinara administranto povas fari ĝin - provite praktike.

Por modifoj, specialistoj kun seriozaj kvalifikoj ne estas bezonataj; scio pri PHP sufiĉas, ĉar Moduloj jam estis skribitaj por la SIP-protokolo, kaj por la atendovico, kaj por voki dungiton, kaj aliajn. Estas envolvaĵklaso por Asterisko. Por evoluigi modulon, programisto povas (kaj laŭ bona maniero devus) voki pretajn modulojn. Kaj scio Asterisko estas tute nenecesaj se la kliento petas aldoni paĝon kun iu nova raporto. Sed praktiko montras, ke kvankam triaj programistoj povas elteni, ili sentas sin nesekuraj sen dokumentado kaj normala priraportado de komentoj, do ankoraŭ estas loko por plibonigo.

Moduloj povas:

  • krei novajn traktadkapablojn,
  • aldonu novajn blokojn al la retinterfaco,
  • heredi de iu el la ekzistantaj moduloj, redifini funkciojn kaj anstataŭigi ĝin, aŭ simple esti iomete modifita kopio,
  • aldonu viajn agordojn al la agorda ŝablono de aliaj moduloj kaj multe pli.

PBX-agordoj per API. Kiel priskribite supre, ĉiuj agordoj estas konservitaj en la datumbazo kaj legitaj en la momento de la voko, do vi povas ŝanĝi ĉiujn PBX-agordojn per la API. Kiam vi vokas la API, la agordo ne estas rekreita kaj la moduloj ne rekomenciĝas, do ne gravas kiom da agordoj kaj dungitoj vi havas. API-petoj estas ekzekutitaj rapide kaj ne blokas unu la alian.

La PBX stokas ĉiujn ŝlosilajn operaciojn kun vokoj kun daŭroj (atendo/konversacio), nestado kaj en PBX-kondiĉoj (dungito, grupo, ekstera linio, ne kanalo, nombro). Ĉi tio permesas vin konstrui diversajn raportojn por specifaj klientoj kaj la plej granda parto de la laboro estas krei uzant-amika interfaco.

La tempo diros, kio okazos poste. Ankoraŭ estas multaj nuancoj, kiujn oni devas refari, estas ankoraŭ multaj planoj, sed unu jaro pasis de la kreado de la 3-a versio kaj ni jam povas diri, ke la ideo funkcias. La ĉefa malavantaĝo de versio 3 estas la aparataj rimedoj, sed ĉi tio estas kutime por kio vi devas pagi por facileco de disvolviĝo.

fonto: www.habr.com

Aldoni komenton