Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Pasti banyak dari Anda, seperti saya, yang punya ide untuk melakukan sesuatu yang unik. Pada artikel ini saya akan menjelaskan masalah teknis dan solusi yang saya hadapi saat mengembangkan PBX. Mungkin ini akan membantu seseorang memutuskan idenya sendiri, dan seseorang mengikuti jalan yang telah dilalui, karena saya juga mendapat manfaat dari pengalaman para pionir.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Ide dan persyaratan utama

Dan semuanya dimulai hanya dengan cinta Asterisk (kerangka untuk membangun aplikasi komunikasi), otomatisasi telepon dan instalasi FreePBX (antarmuka web untuk Asterisk). Jika kebutuhan perusahaan tidak spesifik dan sesuai dengan kemampuan FreePBX - semuanya bagus. Seluruh instalasi berlangsung dalam waktu XNUMX jam, perusahaan menerima PBX yang dikonfigurasi, antarmuka yang ramah pengguna dan pelatihan singkat ditambah dukungan jika diinginkan.

Tetapi tugas yang paling menarik adalah tugas yang tidak standar dan pada saat itu tidak terlalu menakjubkan. Asterisk dapat melakukan banyak hal, tetapi untuk menjaga antarmuka web tetap berfungsi, perlu menghabiskan lebih banyak waktu. Jadi detail kecil bisa memakan waktu lebih lama dibandingkan memasang PBX lainnya. Dan intinya bukan butuh waktu lama untuk menulis antarmuka web, melainkan intinya pada fitur arsitekturalnya FreePBX. Pendekatan dan metode arsitektur FreePBX ditata pada saat php4, dan pada saat itu sudah ada php5.6 di mana segala sesuatunya bisa dibuat lebih sederhana dan nyaman.

Yang terakhir adalah dialplan grafis dalam bentuk diagram. Ketika saya mencoba membangun sesuatu seperti ini untuk FreePBX, saya menyadari bahwa saya harus menulis ulang secara signifikan dan akan lebih mudah untuk membuat sesuatu yang baru.

Persyaratan utamanya adalah:

  • pengaturan sederhana, dapat diakses secara intuitif bahkan oleh administrator pemula. Dengan demikian, perusahaan tidak memerlukan pemeliharaan PBX di pihak kami,
  • modifikasi mudah sehingga tugas diselesaikan dalam waktu yang memadai,
  • kemudahan integrasi dengan PBX. kamu FreePBX tidak ada API untuk mengubah pengaturan, mis. Anda tidak dapat, misalnya, membuat grup atau menu suara dari aplikasi pihak ketiga, hanya API itu sendiri Asterisk,
  • opensource - bagi pemrogram ini sangat penting untuk modifikasi bagi klien.

Ide pengembangan yang lebih cepat adalah agar semua fungsi terdiri dari modul-modul dalam bentuk objek. Semua objek harus memiliki kelas induk yang sama, yang berarti nama semua fungsi utama sudah diketahui dan oleh karena itu sudah ada implementasi default. Objek akan memungkinkan Anda mengurangi secara drastis jumlah argumen dalam bentuk array asosiatif dengan kunci string, yang dapat Anda temukan di FreePBX Hal ini dimungkinkan dengan memeriksa seluruh fungsi dan fungsi yang disarangkan. Dalam kasus objek, pelengkapan otomatis dangkal akan menampilkan semua properti, dan secara umum akan menyederhanakan hidup berkali-kali lipat. Ditambah lagi, pewarisan dan redefinisi telah menyelesaikan banyak masalah dengan modifikasi.

Hal berikutnya yang memperlambat waktu pengerjaan ulang dan patut dihindari adalah duplikasi. Jika ada modul yang bertanggung jawab untuk memanggil seorang karyawan, maka semua modul lain yang perlu mengirim panggilan ke seorang karyawan harus menggunakannya, dan tidak membuat salinannya sendiri. Jadi, jika Anda perlu mengubah sesuatu, maka Anda harus mengubahnya hanya di satu tempat dan pencarian “cara kerjanya” harus dilakukan di satu tempat, dan tidak mencari di seluruh proyek.

Versi pertama dan kesalahan pertama

Prototipe pertama siap dalam waktu satu tahun. Seluruh PBX, seperti yang direncanakan, bersifat modular, dan modul tidak hanya dapat menambahkan fungsionalitas baru untuk memproses panggilan, tetapi juga mengubah antarmuka web itu sendiri.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php
Ya, ide membuat dialplan dalam bentuk skema seperti itu bukan milik saya, tetapi sangat nyaman dan saya melakukan hal yang sama untuk Asterisk.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Dengan menulis sebuah modul, pemrogram sudah dapat:

  • buat fungsionalitas Anda sendiri untuk pemrosesan panggilan, yang dapat ditempatkan pada diagram, serta di menu elemen di sebelah kiri,
  • buat halaman Anda sendiri untuk antarmuka web dan tambahkan templat Anda ke halaman yang ada (jika pengembang halaman telah menyediakannya),
  • tambahkan pengaturan Anda ke tab pengaturan utama atau buat tab pengaturan Anda sendiri,
  • pemrogram dapat mewarisi modul yang sudah ada, mengubah sebagian fungsi dan mendaftarkannya dengan nama baru atau mengganti modul asli.

Misalnya, inilah cara Anda membuat menu suara Anda sendiri:

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

Implementasi rumit pertama membawa kebanggaan pertama dan kekecewaan pertama. Saya senang ini berhasil, karena saya sudah dapat mereproduksi fitur-fitur utama FreePBX. Saya senang orang-orang menyukai gagasan skema ini. Masih banyak pilihan untuk menyederhanakan pengembangan, namun pada saat itu beberapa tugas sudah menjadi lebih mudah.

API untuk mengubah konfigurasi PBX mengecewakan - hasilnya sama sekali tidak sesuai dengan keinginan kami. Saya mengambil prinsip yang sama seperti di FreePBX, dengan mengklik tombol Terapkan, seluruh konfigurasi dibuat ulang dan modul dimulai ulang.

Terlihat seperti ini:

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php
*Dialplan adalah aturan (algoritma) yang digunakan untuk memproses panggilan.

Namun dengan opsi ini, tidak mungkin menulis API normal untuk mengubah pengaturan PBX. Pertama, operasi penerapan perubahan Asterisk terlalu panjang dan intensif sumber daya.
Kedua, Anda tidak dapat memanggil dua fungsi secara bersamaan, karena keduanya akan membuat konfigurasi.
Ketiga, ini menerapkan semua pengaturan, termasuk yang dibuat oleh administrator.

Dalam versi ini, seperti pada Askozia, dimungkinkan untuk membuat konfigurasi hanya modul yang diubah dan memulai ulang hanya modul yang diperlukan, tetapi ini semua hanya setengah-setengah. Pendekatannya perlu diubah.

Versi kedua. Hidung ditarik keluar, ekornya tersangkut

Ide untuk memecahkan masalah ini bukanlah untuk membuat ulang konfigurasi dan dialplan Asterisk, tetapi menyimpan informasi ke database dan membaca dari database secara langsung saat memproses panggilan. Asterisk Saya sudah mengetahui cara membaca konfigurasi dari database, tinggal mengubah nilai di database dan panggilan selanjutnya akan diproses dengan mempertimbangkan perubahan tersebut, dan fungsinya sangat cocok untuk membaca parameter dialplan REALTIME_HASH.

Pada akhirnya, bahkan tidak perlu memulai ulang Asterisk saat mengubah pengaturan dan semua pengaturan mulai diterapkan segera Asterisk.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Satu-satunya perubahan pada dialplan adalah penambahan nomor ekstensi dan petunjuk. Tapi ini hanyalah perubahan kecil

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

Anda dapat dengan mudah menambah atau mengubah saluran di dialplan menggunakan Ami (antarmuka kontrol Asterisk) dan tidak diperlukan reboot seluruh dialplan.

Ini memecahkan masalah dengan konfigurasi API. Anda bahkan dapat langsung masuk ke database dan menambahkan grup baru atau mengubah, misalnya, waktu dial-up di kolom “dialtime” untuk grup tersebut dan panggilan berikutnya akan berlangsung sesuai waktu yang ditentukan (Ini bukan rekomendasi untuk tindakan, karena beberapa operasi API memerlukannya Ami panggilan).

Implementasi pertama yang sulit kembali mendatangkan kebanggaan dan kekecewaan pertama. Saya senang itu berhasil. Basis data menjadi penghubung penting, ketergantungan pada disk meningkat, risiko lebih besar, namun semuanya berjalan stabil dan tanpa masalah. Dan yang paling penting, sekarang segala sesuatu yang dapat dilakukan melalui antarmuka web dapat dilakukan melalui API, dan metode yang sama digunakan. Selain itu, antarmuka web menghilangkan tombol “terapkan pengaturan ke PBX”, yang sering dilupakan oleh administrator.

Yang mengecewakan adalah perkembangannya menjadi lebih rumit. Sejak versi pertama, bahasa PHP telah menghasilkan dialplan dalam bahasa tersebut Asterisk dan tampilannya sama sekali tidak dapat dibaca, ditambah bahasanya sendiri Asterisk untuk menulis dialplan itu sangat primitif.

Seperti apa bentuknya:

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

Pada versi kedua, dialplan menjadi universal, mencakup semua opsi pemrosesan yang memungkinkan tergantung pada parameter dan ukurannya meningkat secara signifikan. Semua ini sangat memperlambat waktu pengembangan, dan pemikiran bahwa sekali lagi perlu mengganggu dialplan membuat saya sedih.

Versi ketiga

Ide untuk memecahkan masalah bukan untuk menghasilkan Asterisk dialplan dari php dan gunakan FastAGI dan tulis semua aturan pemrosesan di PHP itu sendiri. FastAGI memungkinkan Asterisk, untuk memproses panggilan, sambungkan ke soket. Terima perintah dari sana dan kirimkan hasilnya. Dengan demikian, logika dialplan sudah berada di luar batas Asterisk dan dapat ditulis dalam bahasa apa pun, dalam kasus saya di PHP.

Ada banyak trial and error. Masalah utamanya adalah saya sudah memiliki banyak kelas/file. Dibutuhkan sekitar 1,5 detik untuk membuat objek, menginisialisasinya, dan mendaftarkan satu sama lain, dan penundaan per panggilan ini bukanlah sesuatu yang dapat diabaikan.

Inisialisasi seharusnya hanya terjadi satu kali dan oleh karena itu pencarian solusi dimulai dengan menulis layanan dalam php menggunakan Utas. Setelah seminggu bereksperimen, opsi ini ditangguhkan karena rumitnya cara kerja ekstensi ini. Setelah satu bulan pengujian, saya juga harus meninggalkan pemrograman asinkron di PHP; Saya memerlukan sesuatu yang sederhana, familier bagi pemula PHP mana pun, dan banyak ekstensi untuk PHP yang sinkron.

Solusinya adalah layanan multi-thread kami sendiri di C, yang dikompilasi dengan PHPLIB. Ini memuat semua file php ATS, menunggu semua modul diinisialisasi, menambahkan panggilan balik satu sama lain, dan ketika semuanya sudah siap, menyimpannya dalam cache. Saat bertanya lewat FastAGI aliran dibuat, salinan dari cache semua kelas dan data direproduksi di dalamnya, dan permintaan diteruskan ke fungsi php.

Dengan solusi ini, waktu mulai dari mengirim panggilan ke layanan kami hingga perintah pertama Asterisk menurun dari 1,5 detik menjadi 0,05 detik dan kali ini sedikit bergantung pada ukuran proyek.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Hasilnya, waktu untuk pengembangan dialplan berkurang secara signifikan, dan saya menghargai hal ini karena saya harus menulis ulang seluruh dialplan dari semua modul dalam PHP. Pertama, metode harus sudah ditulis dalam php untuk mendapatkan objek dari database; mereka diperlukan untuk ditampilkan di antarmuka web, dan kedua, dan ini adalah hal utama, akhirnya dimungkinkan untuk bekerja dengan nyaman dengan string dengan angka dan array dengan database ditambah banyak ekstensi PHP.

Untuk memproses dialplan di kelas modul Anda perlu mengimplementasikan fungsinya dialplanDynamicCall dan argumen pbxCallRequest akan berisi objek untuk berinteraksi Asterisk.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Selain itu, menjadi mungkin untuk men-debug dialplan (php memiliki xdebug dan berfungsi untuk layanan kami), Anda dapat melanjutkan langkah demi langkah dengan melihat nilai variabel.

Data panggilan

Analisis dan laporan apa pun memerlukan data yang dikumpulkan dengan benar, dan blok PBX ini juga melalui banyak percobaan dan kesalahan dari versi pertama hingga versi ketiga. Seringkali, data panggilan adalah sebuah tanda. Satu panggilan = satu rekaman: siapa yang menelepon, siapa yang menjawab, berapa lama mereka berbicara. Pada pilihan yang lebih menarik, terdapat tanda tambahan yang menunjukkan karyawan PBX mana yang dipanggil saat panggilan berlangsung. Namun semua itu hanya mencakup sebagian dari kebutuhan.

Persyaratan awal adalah:

  • simpan tidak hanya siapa yang menelepon PBX, tetapi juga siapa yang menjawab, karena ada intersepsi dan ini perlu diperhitungkan saat menganalisis panggilan,
  • waktu sebelum terhubung dengan seorang karyawan. Di dalam FreePBX dan beberapa PBX lainnya, panggilan dianggap terjawab segera setelah PBX mengangkat telepon. Namun untuk menu suara sudah perlu mengangkat telepon, sehingga semua panggilan terjawab dan waktu tunggu jawaban menjadi 0-1 detik. Oleh karena itu, diputuskan untuk menghemat tidak hanya waktu sebelum respons, tetapi juga waktu sebelum menghubungkan dengan modul utama (modul itu sendiri yang menyetel tanda ini. Saat ini adalah "Karyawan", "Jalur eksternal"),
  • untuk dialplan yang lebih kompleks, ketika panggilan dilakukan antar grup yang berbeda, setiap elemen perlu diperiksa secara terpisah.

Pilihan terbaik ternyata adalah ketika modul PBX mengirimkan informasi tentang dirinya melalui panggilan dan pada akhirnya menyimpan informasi tersebut dalam bentuk pohon.

Ini terlihat seperti ini:

Pertama, informasi umum tentang panggilan tersebut (seperti orang lain - tidak ada yang istimewa).

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

  1. Menerima panggilan di saluran luar"Untuk ujian"pukul 05:55:52 dari nomor 89295671458 ke nomor 89999999999, akhirnya dijawab oleh seorang karyawan"Sekretaris2» dengan nomor 104. Klien menunggu 60 detik dan berbicara selama 36 detik.
  2. Karyawan "Sekretaris2"menelepon ke 112 dan seorang karyawan menjawab"Manajer1» setelah 8 detik. Mereka berbicara selama 14 detik.
  3. Klien dialihkan ke Karyawan "manajer1" di mana mereka terus berbicara selama 13 detik

Tapi ini adalah puncak gunung es; untuk setiap catatan Anda bisa mendapatkan riwayat panggilan terperinci melalui PBX.

Kisah satu proyek atau bagaimana saya menghabiskan 7 tahun membuat PBX berdasarkan Asterisk dan Php

Semua informasi disajikan sebagai kumpulan panggilan:

  1. Menerima panggilan di saluran luar"Untuk ujian» pada 05:55:52 dari nomor 89295671458 ke nomor 89999999999.
  2. Pada 05:55:53 saluran luar mengirimkan panggilan ke sirkuit Masuk "uji»
  3. Saat memproses panggilan sesuai dengan skema, modul “panggilan manajer", yang durasi panggilannya adalah 16 detik. Ini adalah modul yang dikembangkan untuk klien.
  4. Modul "panggilan manajer" mengirimkan panggilan ke karyawan yang bertanggung jawab atas nomor tersebut (klien) "Manajer1” dan menunggu 5 detik untuk mendapat tanggapan. Manajer tidak menjawab.
  5. Modul "panggilan manajer"mengirim panggilan ke grup"manajer CORP" Ini adalah manajer lain dengan arah yang sama (duduk di ruangan yang sama) dan menunggu 11 detik untuk mendapat tanggapan.
  6. Grup "manajer CORP"menelepon karyawan"Manajer1, Manajer2, Manajer3"secara bersamaan selama 11 detik. Tidak ada Jawaban.
  7. Panggilan manajer berakhir. Dan rangkaian mengirimkan panggilan ke modul "Memilih rute dari 1c" Juga modul yang ditulis untuk klien. Di sini panggilan diproses selama 0 detik.
  8. Sirkuit mengirimkan panggilan ke menu suara "Dasar dengan panggilan tambahan" Klien menunggu disana selama 31 detik, tidak ada panggilan tambahan.
  9. Skema mengirimkan panggilan ke Grup "Sekretaris", dimana klien menunggu 12 detik.
  10. Dalam satu kelompok, 2 orang pegawai dipanggil sekaligus"Sekretaris1"Dan"Sekretaris2" dan setelah 12 detik karyawan tersebut menjawab "Sekretaris2" Jawaban atas panggilan tersebut diduplikasi menjadi panggilan induk. Ternyata di grup dia menjawab “Sekretaris2", saat menelpon rangkaian dijawab"Sekretaris2" dan menjawab panggilan di saluran luar dengan "Sekretaris2'.

Penyimpanan informasi tentang setiap operasi dan sarangnya akan memungkinkan pembuatan laporan dengan mudah. Laporan pada menu suara akan membantu Anda mengetahui seberapa besar bantuan atau hambatannya. Buatlah laporan panggilan tidak terjawab oleh karyawan, dengan mempertimbangkan bahwa panggilan tersebut disadap sehingga tidak dianggap tidak terjawab, dan dengan mempertimbangkan bahwa itu adalah panggilan grup, dan orang lain menjawab lebih awal, yang berarti panggilan tersebut juga tidak terjawab.

Penyimpanan informasi tersebut akan memungkinkan Anda untuk mengambil setiap kelompok secara terpisah dan menentukan seberapa efektif kerjanya, dan membuat grafik kelompok yang dijawab dan tidak terjawab per jam. Anda juga dapat memeriksa seberapa akurat koneksi ke manajer yang bertanggung jawab dengan menganalisis transfer setelah terhubung ke manajer.

Anda juga dapat melakukan penelitian yang tidak biasa, misalnya, seberapa sering nomor yang tidak ada dalam database menghubungi ekstensi yang benar atau berapa persentase panggilan keluar yang diteruskan ke ponsel.

Hasilnya?

Seorang spesialis tidak diharuskan untuk memelihara PBX, administrator paling biasa dapat melakukannya - telah teruji dalam praktiknya.

Untuk modifikasi tidak diperlukan tenaga ahli dengan kualifikasi yang serius, pengetahuan tentang PHP sudah cukup, karena Modul telah ditulis untuk protokol SIP, dan untuk antrian, dan untuk memanggil karyawan, dan lain-lain. Ada kelas pembungkus untuk Asterisk. Untuk mengembangkan sebuah modul, seorang programmer dapat (dan seharusnya) memanggil modul yang sudah jadi. Dan pengetahuan Asterisk sama sekali tidak diperlukan jika klien meminta untuk menambahkan halaman dengan beberapa laporan baru. Namun praktik menunjukkan bahwa meskipun pemrogram pihak ketiga dapat mengatasinya, mereka merasa tidak aman tanpa dokumentasi dan liputan komentar yang normal, sehingga masih ada ruang untuk perbaikan.

Modul dapat:

  • membuat kemampuan pemrosesan panggilan baru,
  • tambahkan blok baru ke antarmuka web,
  • mewarisi dari salah satu modul yang ada, mendefinisikan ulang fungsi dan menggantinya, atau sekadar menjadi salinan yang sedikit dimodifikasi,
  • tambahkan pengaturan Anda ke templat pengaturan modul lain dan banyak lagi.

Pengaturan PBX melalui API. Seperti dijelaskan di atas, semua pengaturan disimpan dalam database dan dibaca pada saat panggilan dilakukan, sehingga Anda dapat mengubah semua pengaturan PBX melalui API. Saat memanggil API, konfigurasi tidak dibuat ulang dan modul tidak dimulai ulang, oleh karena itu, tidak masalah berapa banyak pengaturan dan karyawan yang Anda miliki. Permintaan API dieksekusi dengan cepat dan tidak saling memblokir.

PBX menyimpan semua operasi utama dengan panggilan dengan durasi (menunggu/percakapan), bersarang dan dalam istilah PBX (karyawan, grup, saluran eksternal, bukan saluran, nomor). Hal ini memungkinkan Anda membuat berbagai laporan untuk klien tertentu dan sebagian besar pekerjaannya adalah membuat antarmuka yang ramah pengguna.

Waktu akan memberi tahu apa yang akan terjadi selanjutnya. Masih banyak nuansa yang perlu diperbaiki, masih banyak rencana, namun setahun telah berlalu sejak pembuatan versi ke-3 dan kita sudah bisa mengatakan bahwa idenya berhasil. Kerugian utama dari versi 3 adalah sumber daya perangkat keras, tetapi biasanya ini adalah hal yang harus Anda bayar untuk kemudahan pengembangan.

Sumber: www.habr.com

Tambah komentar