La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

Segur que molts de vosaltres, com jo, vau tenir una idea de fer alguna cosa única. En aquest article descriuré els problemes tècnics i les solucions que vaig haver d'enfrontar a l'hora de desenvolupar la central. Potser això ajudarà a algú a decidir sobre la seva pròpia idea, i algú a seguir el camí ben fressat, perquè també em vaig beneficiar de l'experiència dels pioners.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

Idea i requisits clau

I tot va començar simplement amb amor per Asterisc (marc d'aplicacions de comunicació d'edificis), automatització de telefonia i instal·lacions PBX gratuïta (interfície web per Asterisc). Si les necessitats de l'empresa fossin sense especificitats i estaven dins de les capacitats PBX gratuïta - tot és genial. Tota la instal·lació es va dur a terme en XNUMX hores, l'empresa va rebre una PBX configurada, una interfície fàcil d'utilitzar i una formació curta i suport si ho desitjava.

Però les tasques més interessants eren no estàndard i després no era tan fabulosa. Asterisc pot fer molt, però per mantenir la interfície web en bon funcionament, va ser necessari dedicar moltes vegades més temps. Per tant, un petit detall podria trigar molt més que instal·lar la resta de la central. I la qüestió no és que es trigui molt de temps a escriure una interfície web, sinó que la qüestió està en les característiques arquitectòniques. PBX gratuïta. Enfocaments i mètodes de l'arquitectura PBX gratuïta es va dissenyar en el moment de php4, i en aquell moment ja hi havia php5.6 on tot es podia fer més senzill i còmode.

L'última gota van ser plànols de marca gràfics en forma de diagrama. Quan vaig intentar construir una cosa així per PBX gratuïta, em vaig adonar que l'hauria de reescriure significativament i que seria més fàcil construir alguna cosa nova.

Els requisits clau eren:

  • configuració senzilla, accessible de manera intuïtiva fins i tot per a un administrador novell. Així, les empreses no requereixen manteniment de PBX per la nostra part,
  • modificació fàcil perquè les tasques es resolguin en el temps adequat,
  • facilitat d'integració amb PBX. U PBX gratuïta no hi havia cap API per canviar la configuració, és a dir. No podeu, per exemple, crear grups o menús de veu des d'una aplicació de tercers, només la pròpia API Asterisc,
  • codi obert: per als programadors, això és extremadament important per a les modificacions del client.

La idea d'un desenvolupament més ràpid era que tota la funcionalitat consistís en mòduls en forma d'objectes. Tots els objectes havien de tenir una classe pare comuna, el que significa que els noms de totes les funcions principals ja es coneixen i, per tant, ja hi ha implementacions per defecte. Els objectes us permetran reduir dràsticament el nombre d'arguments en forma de matrius associatives amb claus de cadena, que podeu esbrinar a PBX gratuïta Va ser possible examinant la funció sencera i les funcions imbricades. En el cas dels objectes, l'autocompleció banal mostrarà totes les propietats i, en general, simplificarà la vida moltes vegades. A més, l'herència i la redefinició ja resol molts problemes amb les modificacions.

El següent que va alentir el temps de reelaboració i que valia la pena evitar va ser la duplicació. Si hi ha un mòdul responsable de marcar un empleat, tots els altres mòduls que necessiten enviar una trucada a un empleat haurien d'utilitzar-lo i no crear-ne les seves pròpies còpies. Per tant, si necessiteu canviar alguna cosa, haureu de canviar només en un lloc i la cerca de "com funciona" s'ha de dur a terme en un sol lloc i no a tot el projecte.

Primera versió i primers errors

El primer prototip estava llest en un any. Tota la PBX, tal com estava previst, era modular i els mòduls no només podien afegir noves funcionalitats per processar trucades, sinó també canviar la interfície web.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php
Sí, la idea de crear un pla de marcatge en forma d'aquest esquema no és meva, però és molt convenient i vaig fer el mateix per Asterisc.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

En escriure un mòdul, els programadors ja podrien:

  • creeu la vostra pròpia funcionalitat per al processament de trucades, que es pot col·locar al diagrama, així com al menú d'elements de l'esquerra,
  • creeu les vostres pròpies pàgines per a la interfície web i afegiu les vostres plantilles a les pàgines existents (si el desenvolupador de la pàgina ho ha proporcionat),
  • afegiu la vostra configuració a la pestanya de configuració principal o creeu la vostra pròpia pestanya de configuració,
  • el programador pot heretar d'un mòdul existent, canviar part de la funcionalitat i registrar-la amb un nom nou o substituir el mòdul original.

Per exemple, així és com podeu crear el vostre propi menú de veu:

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

Les primeres implementacions complexes van portar el primer orgull i les primeres decepcions. Em va alegrar que funcionés, que ja pogués reproduir les característiques principals PBX gratuïta. Em va alegrar que a la gent li agradi la idea de l'esquema. Encara hi havia moltes opcions per simplificar el desenvolupament, però fins i tot en aquell moment algunes de les tasques ja s'estaven facilitant.

L'API per canviar la configuració de la central va ser una decepció: el resultat no va ser gens el que volíem. Vaig agafar el mateix principi que en PBX gratuïta, fent clic al botó Aplica, es recrea tota la configuració i es reinicien els mòduls.

Es veu així:

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php
*Dialplan és una regla (algorisme) per la qual es processa una trucada.

Però amb aquesta opció, és impossible escriure una API normal per canviar la configuració de la central. En primer lloc, l'operació d'aplicar canvis a Asterisc massa llarg i requereix molt recursos.
En segon lloc, no podeu cridar dues funcions al mateix temps, perquè tots dos crearan la configuració.
En tercer lloc, aplica tots els paràmetres, inclosos els fets per l'administrador.

En aquesta versió, com en Askozia, es va poder generar la configuració només dels mòduls modificats i reiniciar només els mòduls necessaris, però tots són mitges mesures. Calia canviar el plantejament.

Segona versió. El nas treu la cua enganxada

La idea per resoldre el problema no era recrear la configuració i el pla de marcació Asterisc, però deseu informació a la base de dades i llegiu-la directament mentre processeu la trucada. Asterisc Ja sabia llegir configuracions de la base de dades, només cal canviar el valor a la base de dades i la següent trucada es processarà tenint en compte els canvis, i la funció era perfecta per llegir els paràmetres del pla de marcatge REALTIME_HASH.

Al final, no calia ni tan sols reiniciar Asterisc quan es va canviar la configuració i es van començar a aplicar immediatament tots els paràmetres Asterisc.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

Els únics canvis al pla de marcació són l'addició de números d'extensió i consells. Però aquests eren petits canvis puntuals

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

Podeu afegir o canviar fàcilment una línia al pla de marcatge mitjançant Ami (interfície de control Asterisc) i no cal reiniciar tot el pla de marcatge.

Això va resoldre el problema amb l'API de configuració. Fins i tot podríeu entrar directament a la base de dades i afegir un grup nou o canviar, per exemple, l'hora d'accés telefònic al camp "hora de marcatge" del grup i la trucada següent ja duraria el temps especificat (Aquesta no és una recomanació per a acció, ja que algunes operacions de l'API requereixen Ami trucades).

Les primeres implementacions difícils van tornar a portar el primer orgull i la decepció. Em vaig alegrar que funcionés. La base de dades es va convertir en un enllaç crític, la dependència del disc va augmentar, hi havia més riscos, però tot va funcionar de manera estable i sense problemes. I el més important, ara tot el que es podia fer a través de la interfície web es podia fer a través de l'API, i es feien servir els mateixos mètodes. A més, la interfície web es va desfer del botó "aplica la configuració a PBX", que els administradors sovint s'obliden.

La decepció va ser que el desenvolupament es va complicar. Des de la primera versió, el llenguatge PHP ha generat un pla de marcació en el llenguatge Asterisc i sembla completament il·legible, a més de l'idioma en si Asterisc per escriure un dialplan és extremadament primitiu.

Com es veia:

$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 segona versió, el dialplan es va fer universal, incloïa totes les opcions de processament possibles segons els paràmetres i la seva mida va augmentar significativament. Tot això va frenar molt el temps de desenvolupament, i el fet de pensar que una vegada més era necessari interferir en el pla de marcació em va entristir.

Tercera versió

La idea de resoldre el problema no era generar Asterisc dialplan des de php i utilitzar FastAGI i escriu totes les regles de processament al mateix PHP. FastAGI permet Asterisc, per processar la trucada, connecteu-vos a la presa. Rebeu ordres des d'allà i envieu resultats. Així, la lògica del dialplan ja està fora dels límits Asterisc i es pot escriure en qualsevol idioma, en el meu cas en PHP.

Hi va haver molts assaigs i errors. El problema principal era que ja tenia moltes classes/fitxers. Va trigar uns 1,5 segons a crear objectes, inicialitzar-los i registrar-se entre ells, i aquest retard per trucada no és una cosa que es pugui ignorar.

La inicialització només hauria d'haver passat una vegada i, per tant, la recerca d'una solució va començar amb l'escriptura d'un servei en php utilitzant Pthreads. Després d'una setmana d'experimentació, aquesta opció es va abandonar a causa de les complexitats de com funciona aquesta extensió. Després d'un mes de proves, també vaig haver d'abandonar la programació asíncrona en PHP; necessitava alguna cosa senzilla, familiar per a qualsevol principiant de PHP, i moltes extensions de PHP són sincròniques.

La solució va ser el nostre propi servei multiprocés en C, amb el qual es va compilar PHPLIB. Carrega tots els fitxers ATS php, espera que s'inicialitzin tots els mòduls, s'afegeix una devolució de trucada i, quan tot està llest, ho guarda a la memòria cau. En consultar per FastAGI es crea un flux, s'hi reprodueix una còpia de la memòria cau de totes les classes i dades i la sol·licitud es passa a la funció php.

Amb aquesta solució, el temps des de l'enviament d'una trucada al nostre servei fins a la primera comanda Asterisc va disminuir d'1,5 s a 0,05 s i aquest temps depèn lleugerament de la mida del projecte.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

Com a resultat, el temps per al desenvolupament del dialplan es va reduir significativament, i ho puc apreciar ja que vaig haver de reescriure tot el dialplan de tots els mòduls en PHP. En primer lloc, els mètodes ja s'han d'escriure en php per obtenir un objecte de la base de dades; es necessitaven per mostrar-los a la interfície web i, en segon lloc, i això és el més important, finalment és possible treballar còmodament amb cadenes amb números i matrius. amb base de dades i moltes extensions PHP.

Per processar el dialplan a la classe del mòdul, cal implementar la funció dialplanDynamicCall i argumentació pbxCallRequest contindrà un objecte amb el qual interactuar Asterisc.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

A més, es va fer possible depurar el dialplan (php té xdebug i funciona per al nostre servei), es pot moure pas a pas visualitzant els valors de les variables.

Dades de la trucada

Qualsevol anàlisi i informes requereixen dades recollides correctament, i aquest bloc PBX també va passar per moltes proves i errors des de la primera fins a la tercera versió. Sovint, les dades de la trucada són un signe. Una trucada = una gravació: qui ha trucat, qui ha contestat, quant de temps han parlat. En les opcions més interessants, hi ha un rètol addicional que indica a quin empleat de PBX es va trucar durant la trucada. Però tot això cobreix només una part de les necessitats.

Els requisits inicials eren:

  • estalvieu no només a qui va trucar la central, sinó també a qui va respondre, perquè hi ha intercepcions i això s'haurà de tenir en compte a l'hora d'analitzar les trucades,
  • temps abans de connectar amb un empleat. En PBX gratuïta i alguns altres PBX, la trucada es considera contestada tan bon punt la PBX agafa el telèfon. Però per al menú de veu ja cal agafar el telèfon, de manera que es responen totes les trucades i el temps d'espera per a una resposta es converteix en 0-1 segon. Per tant, es va decidir estalviar no només el temps abans d'una resposta, sinó el temps abans de connectar-se amb mòduls clau (el mòdul mateix estableix aquesta bandera. Actualment és "Empleat", "Línia externa"),
  • per a un dialplan més complex, quan una trucada viatja entre diferents grups, calia poder examinar cada element per separat.

La millor opció va resultar ser quan els mòduls PBX envien informació sobre ells mateixos a les trucades i finalment desen la informació en forma d'arbre.

Es veu així:

En primer lloc, informació general sobre la trucada (com tots els altres, res especial).

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

  1. He rebut una trucada en una línia externa "Per a la massa"a les 05:55:52 del número 89295671458 al número 89999999999, al final va ser contestat per un empleat"Secretari 2» amb el número 104. El client va esperar 60 segons i va parlar durant 36 segons.
  2. Empleat"Secretari 2"truca al 112 i un empleat respon"Gerent 1» al cap de 8 segons. Parlen durant 14 segons.
  3. El client es transfereix a l'empleat "gerent 1"on continuen parlant durant 13 segons més

Però aquesta és la punta de l'iceberg; per a cada registre podeu obtenir un historial de trucades detallat a través de la central.

La història d'un projecte o com vaig passar 7 anys creant un PBX basat en Asterisk i Php

Tota la informació es presenta com un nid de trucades:

  1. He rebut una trucada en una línia externa "Per a la massa» a les 05:55:52 del número 89295671458 al número 89999999999.
  2. A les 05:55:53 la línia exterior envia una trucada al circuit d'entrada "prova»
  3. Quan es processa una trucada segons l'esquema, el mòdul "trucada del gestor", en què la trucada és de 16 segons. Aquest és un mòdul desenvolupat per al client.
  4. mòdul "trucada del gestor" envia una trucada a l'empleat responsable del número (client) "Gerent 1” i espera 5 segons per rebre una resposta. El gerent no va respondre.
  5. mòdul "trucada del gestor"envia una trucada al grup"Gestors de CORP" Aquests són altres gestors de la mateixa direcció (asseguts a la mateixa habitació) i esperant 11 segons una resposta.
  6. Grup "Gestors de CORP"truca als empleats"Gerent 1, Gerent 2, Gerent 3"simultàniament durant 11 segons. Sense resposta.
  7. S'acaba la trucada del gerent. I el circuit envia una trucada al mòdul "Seleccionant una ruta de 1c" També un mòdul escrit per al client. Aquí la trucada s'ha processat durant 0 segons.
  8. El circuit envia una trucada al menú de veu "Bàsic amb marcatge addicional" El client va esperar allà durant 31 segons, no hi va haver cap marcatge addicional.
  9. El pla envia una crida al Grup "Secretaris", on el client va esperar 12 segons.
  10. En un grup, s'anomenen 2 empleats al mateix temps "Secretari 1"I"Secretari 2"i després de 12 segons l'empleat respon"Secretari 2" La resposta a la trucada es duplica en trucades dels pares. Resulta que al grup va respondre “Secretari 2", en trucar al circuit va respondre "Secretari 2" i va respondre la trucada a la línia exterior amb "Secretari 2».

És l'emmagatzematge d'informació sobre cada operació i la seva nidificació el que permetrà simplement fer informes. Un informe al menú de veu us ajudarà a esbrinar fins a quin punt ajuda o dificulta. Elaborar un informe sobre les trucades perdudes pels empleats, tenint en compte que la trucada va ser interceptada i, per tant, no es considera perduda, i tenint en compte que es tractava d'una trucada de grup, i algú més va respondre abans, la qual cosa significa que la trucada tampoc no es va perdre.

Aquest emmagatzematge d'informació us permetrà prendre cada grup per separat i determinar amb quina eficàcia funciona, i crear un gràfic dels grups resposts i perduts per hora. També podeu comprovar la precisió de la connexió amb el gestor responsable analitzant les transferències després de connectar-vos amb el gestor.

També podeu fer estudis força atípics, per exemple, amb quina freqüència els números que no es troben a la base de dades marquen l'extensió correcta o quin percentatge de trucades sortints es desvien a un telèfon mòbil.

El resultat?

No es requereix un especialista per mantenir la PBX; l'administrador més normal pot fer-ho, provat a la pràctica.

Per a les modificacions, no es necessiten especialistes amb qualificacions serioses; el coneixement de PHP és suficient, perquè Ja s'han escrit mòduls per al protocol SIP, i per a la cua, i per trucar a un empleat i altres. Hi ha una classe d'embolcalls per Asterisc. Per desenvolupar un mòdul, un programador pot (i en bona manera hauria) cridar mòduls ja fets. I coneixement Asterisc són completament innecessaris si el client demana afegir una pàgina amb algun informe nou. Però la pràctica demostra que, tot i que els programadors de tercers poden fer front, se senten insegurs sense documentació i una cobertura normal dels comentaris, de manera que encara hi ha marge de millora.

Els mòduls poden:

  • crear noves capacitats de processament de trucades,
  • afegir nous blocs a la interfície web,
  • heretar de qualsevol dels mòduls existents, redefinir funcions i substituir-lo, o simplement ser una còpia lleugerament modificada,
  • afegiu la vostra configuració a la plantilla de configuració d'altres mòduls i molt més.

Configuració de PBX mitjançant API. Com es descriu anteriorment, tots els paràmetres s'emmagatzemen a la base de dades i es llegeixen en el moment de la trucada, de manera que podeu canviar tots els paràmetres de la central mitjançant l'API. Quan es crida a l'API, la configuració no es recrea i els mòduls no es reinicien, per tant, no importa quants paràmetres i empleats tinguis. Les sol·licituds de l'API s'executen ràpidament i no es bloquegen entre elles.

La central emmagatzema totes les operacions clau amb trucades amb durada (espera/conversa), nidificació i en termes de PBX (empleat, grup, línia externa, no canal, número). Això us permet crear diversos informes per a clients específics i la major part del treball és crear una interfície fàcil d'utilitzar.

El temps dirà què passarà després. Encara queden molts matisos per refer, encara queden molts plans, però ha passat un any des de la creació de la 3a versió i ja podem dir que la idea funciona. El principal desavantatge de la versió 3 són els recursos de maquinari, però normalment això és el que cal pagar per facilitar el desenvolupament.

Font: www.habr.com

Afegeix comentari