Користувальницькькі налаштування

Налаштування сайту


Сайдбар

Розділи

Загальний опис
Історія змін
Рекомендації щодо оновлення
Плани на майбутнє
Відомі проблеми
Онлайн демо
Допомога проєкту
Люди
Трохи про безпеку

FAQ



Редагувати сайдбар

telepony

Незаморочений кол-центр

В середньостатистичного ISP, функціонування колцентру/техпідтримки зводиться до двох простих речей:

  • Провайдеру телефонують абоненти, котрі від нього щось хочуть.
  • Працівники кол-центру підіймають трубку та розмовляють з ними ротом, намагаючись вирішити їхні проблеми.

Усе. Нічого більше глобально не відбувається. Все інше це вторинні штуки і розширення, призначені суто для підвищення зручності, отримання статистики, контролю якості та розуміння того, що відбувається у вищеописаних двох пунктах.

За звичай, в інтернетах ще прийнято ілюструвати це все якимись такими добрими картинками, на кшталт таких:

чи такими

або навіть такими, ну щоб “взагалі на серйозних щах”

Так-так, більше усміхнених і щасливих людей! Так! Ще більше! Йоу! Щасливий персонал, котрий контактує з клієнтами! Це ж так реалістично… ага..

Ну, ви ж розумієте, куди ви потрапили, де ви це читаєте і що далі подібної херні не буде? Так?

Що потрібно?

Для реалізації основного функціоналу колцентру вам знадобляться:

  1. Бажання.
  2. Люди, які здатні розмовляти на потрібні вам теми по телефону
  3. Якась PBX, щоб комутувати ці всі розмови

Тут усе зрозуміло. Для цього взагалі можна нічого особливо не робити. Воно “якось робиться” і “якось працює”. Фактично саме по-собі.

Але можливо вам захочеться наступних речей:

  • Хоч якось внятно керувати тим, як, кому і куди додзвонюватимуться ваші абоненти
  • Хоч якось нотифікувати їх що “чекайте-чекайте, ми ось зараз як трубку піднімемо!”
  • Хоч якось сповіщати їх про те, що “вибачте дорогенькі, о четвертій годині ранку ми спимо”.
  • Щоб, ваш персонал, дізнавався про те, хто йому телефонує ще до підняття трубки
  • Мати можливість запису/прослуховування всіх розмов
  • Мати можливість дізнатися коли дзвонив користувач, а також можливість швидко прослухати всі попередні розмови з ним
  • Мати загальну статистику за дзвінками, що відбулися, порахувати кількість відповідей/невідповідей
  • Мати можливість передзвонити на пропущені дзвінки абонентів, та контролювати наскільки добре це відбувається
  • Мати можливість оцінити ККД вашого кол-центру загалом
  • Мати можливість швидко дізнатися про дзвінки у неробочий час та якось їх обробити.

Власне всі вищевикладені речі, в тому чи іншому вигляді, цілком можна реалізувати за допомогою інтеграції вашої PBX з Ubilling.

А як?

Власне типовий і рандомно-масштабований кейс типового кол центру виглядає якось так:

(саппортів намальовано три штуки, щоб вони могли по черзі обійматися і плакати)

PBX ми будемо використовувати On-Premise Asterisk, оскільки боротись з тарганами в голові нікому невідомих SaaS ми не хочемо і в принципі не маємо здоров'я розбиратись з цим за вас. Також поряд там намальовано GSM-to-SIP gateway, в який можна натицяти SIM-карток та приймати виклики ними. Якщо вам дуже хочеться аби ми “порадили якийсь нормальний”, то нехай це буде, щось типу Yeastar TGХХХ. Якщо вам дуже цікаво знати, як це все налаштовується та інтегрується з Asterisk - дайте нам знати, скажімо отут @Ubilling.

В подальшому будуть використовуватись наступні дані, для прикладу:

Дані з прикладу Що це?
192.168.0.162/24 IP адреса нашого серверу з Asterisk
em1 Інтерфейс, через котрий ми будемо спілкуватись з PBX
192.168.0.161/24 IP адреса нашого біллінгового серверу з Ubilling
172.16.42.0/24 та 192.168.0.0/24 умовно “безпечні мережі” де знаходяться наше обладнання, телефони, працівники, тощо
185.45.152.0/22 та 195.5.0.54/32 Мережі та адреси ззовні нашої мережі, де знаходяться наші SIP-провайдери
444444 Номер отриманий від сервісу Zadarma. Він же логін.
0800123456 Вхідний багатоканальний 0800 номер від Укртелекому, насправді 0800 працюють як “аліаси” і дзвінки з них надходять на “справжній номер”
0333333333 Наш справжній номер Укртелекому, на який прилітатиме усе, що дзвонить на 0800123456 а також кудою ми будемо здійснювати вихидні дзвінки за замовчуванням. Він же логін.
195.5.0.54 IP адреса SIP транку Укртелекому
sip.zadarma.com Хост SIP транку сервісу Zadarma
zadarmasecretpassword Пароль сервісу Zadarma
verysecretmysqlrootpassword root-пароль на MySQL серверу телефонії
asteriskmysqlpassword пароль MySQL користувача asterisk - використовувається для з'єднання з БД як самим Aterisk для запису CDR, так і біллінгом для читання CDR
UBxxxxxxxxxxxxxxxxxxxxx Серійний номер вашого працюючого Ubilling
http://192.168.0.161/billing/ Повний URL веб інтерфейсу вашого Ubilling
sharedsippassword Загальний пароль наших SIP телефонів, це має сенс якщо всі їх налаштовує ваш адміністратор та стоять вони у вас десь в офісі
bosspassword Пароль на конкретний SIP телефон, який демонструє своїм виглядом, як використовувати конкретний пароль не наслідуючи “загальний” для якогось конкретного пристрою
08:00-20:00 Робочий час роботи техпідтримки
20:00-08:00 Час “нічного режиму”
maryana,mariya,markiyan Логіни та відповідно імена працівників служби техпідтримки, котрі приймають дзвінки
121,122,123 SIP номери працівників техпідтримки, котрі приймають дзвінки в рамках черги
120 SIP номер, котрий може телефонувати куди йому заманеться, але дзвінки від клієнтів не будуть до нього потрапляти

Налаштовуємо Asterisk з нуля

У праву руку беремо чисту FreeBSD 13.2 та ставимо все необхідне нам ПЗ.

# pkg install -y asterisk18
# pkg install -y mysql80-server
# pkg install -y lame
# pkg install -y sox

Редагуємо наш /etc/rc.conf якось так

rc.conf
hostname="sip"
ifconfig_em1="inet 192.168.0.162/24"
defaultrouter="192.168.0.1"
sshd_enable="YES"
dumpdev="AUTO"
 
 
#firewall
firewall_enable="YES"
firewall_nat_enable="YES"
dummynet_enable="YES"
firewall_script="/etc/firewall.conf"
 
#fsck no bg
fsck_y_enable="YES"
background_fsck="NO"
 
#asterisk and mysql
mysql_enable="YES"
asterisk_enable="YES"
 
#nfs for calls archive export
rpcbind_enable="YES"
nfs_server_enable="YES"
nfs_server_flags="-u -t -n 4"
mountd_enable="YES"
mountd_flags="-r"

Запихаємо все потрібне до /boot/loader.conf

loader.conf
kern.hz="1000"
ipfw_load="YES"
net.inet.ip.fw.default_to_accept="1"
libalias_load="YES"
ipfw_nat_load="YES"
dummynet_load="YES"

І хоч якось намагаємося подбати про свою безпеку використовуючи якийсь такий /etc/firewall.conf

# touch /etc/firewall.conf
# chmod a+x /etc/firewall.conf
firewall.conf
#!/bin/sh
 
# firewall command
FwCMD="/sbin/ipfw -q"
 
${FwCMD} -f flush
 
#safe networks define
${FwCMD} table 22 add 127.0.0.1
${FwCMD} table 22 add 192.168.0.0/24
${FwCMD} table 22 add 172.16.42.0/24
 
#peers
${FwCMD} table 22 add 185.45.152.0/22
${FwCMD} table 22 add 195.5.0.54
 
#safe zones
${FwCMD} add 45 allow ip from table\(22\) to me
${FwCMD} add 45 allow ip from me to table\(22\)
 
#ssh access
${FwCMD} add 46 deny ip from any to me  dst-port 22
${FwCMD} add 46 deny ip from me to any src-port 22
 
#snmp access
${FwCMD} add 47 deny ip from any to me  dst-port 161
${FwCMD} add 47 deny ip from me to any src-port 161
 
#SIP access
${FwCMD} add 48 deny ip from any to me  dst-port 5060
${FwCMD} add 48 deny ip from me to any src-port 5060
 
#mysql access
${FwCMD} add 49 deny ip from any to me  dst-port 3306
${FwCMD} add 49 deny ip from me to any src-port 3306
 
#Asterisk misc
${FwCMD} add 50 deny ip from any to me dst-port 28533
${FwCMD} add 50 deny ip from me to any src-port 28533
 
${FwCMD} add 50 deny ip from any to me dst-port 2727  
${FwCMD} add 50 deny ip from me to any src-port 2727  
 
${FwCMD} add 50 deny ip from any to me dst-port 4569 
${FwCMD} add 50 deny ip from me to any src-port 4569 
 
${FwCMD} add 50 deny ip from any to me dst-port 4520 
${FwCMD} add 50 deny ip from me to any src-port 4520 
 
#NFS 
${FwCMD} add 51 deny ip from any to me dst-port 111
${FwCMD} add 51 deny ip from me to any src-port 111
 
${FwCMD} add 51 deny ip from any to me dst-port 601
${FwCMD} add 51 deny ip from me to any src-port 601
 
${FwCMD} add 51 deny ip from any to me dst-port 602
${FwCMD} add 51 deny ip from me to any src-port 602
 
${FwCMD} add 51 deny ip from any to me dst-port 2049
${FwCMD} add 51 deny ip from me to any src-port 2049
 
${FwCMD} add 65535 allow all from any to any

Встановлюємо рутовий пароль на MySQL у випадку, якщо було згенеровано тимчасовий:

# service mysql-server start
# cat /root/.mysql_secret
# set OMP=`cat /root/.mysql_secret | tail -n 1` && mysqladmin -u root -p"${OMP}" password verysecretmysqlrootpassword

або ж просто змінуємо пароль на необхідний, якщо /root/.mysql_secret не існує:

# cat /root/.mysql_secret
cat: /root/.mysql_secret: No such file or directory
# mysqladmin -u root password verysecretmysqlrootpassword

Попередньо готуємо базу даних для зберігання наших CDR

# mysql -u root -pverysecretmysqlrootpassword
CREATE DATABASE asterisk;

CREATE USER 'asterisk'@'%' IDENTIFIED BY 'asteriskmysqlpassword';
GRANT ALL PRIVILEGES ON *.* TO 'asterisk'@'%' WITH GRANT OPTION;

USE asterisk;

CREATE TABLE `cdr` (
  `calldate` datetime NOT NULL DEFAULT '1970-01-01 00:00:01',
  `clid` varchar(80) NOT NULL DEFAULT '',
  `src` varchar(80) NOT NULL DEFAULT '',
  `dst` varchar(80) NOT NULL DEFAULT '',
  `dcontext` varchar(80) NOT NULL DEFAULT '',
  `channel` varchar(80) NOT NULL DEFAULT '',
  `dstchannel` varchar(80) NOT NULL DEFAULT '',
  `lastapp` varchar(80) NOT NULL DEFAULT '',
  `lastdata` varchar(80) NOT NULL DEFAULT '',
  `duration` int(11) NOT NULL DEFAULT '0',
  `billsec` int(11) NOT NULL DEFAULT '0',
  `disposition` varchar(45) NOT NULL DEFAULT '',
  `amaflags` int(11) NOT NULL DEFAULT '0',
  `accountcode` varchar(20) NOT NULL DEFAULT '',
  `userfield` varchar(255) NOT NULL DEFAULT '',
  `uniqueid` varchar(32) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


ALTER TABLE `cdr`
  ADD KEY `calldate` (`calldate`),
  ADD KEY `dst` (`dst`),
  ADD KEY `uniqueid` (`uniqueid`);
COMMIT;

exit

а також готуємо місце для експорту записів дзвінків в NFS:

# mkdir /mnt/calls 
# chmod 777 /mnt/calls
# echo "/mnt/calls -alldirs -maproot=root 192.168.0.161" > /etc/exports

а також місце, де ми зберігатимемо всю нашу кастомну озвучку

# mkdir /usr/local/etc/asterisk/ivr_media/
# mkdir /usr/local/etc/asterisk/ivr_media/dasmusic
# chmod -R 777 /usr/local/etc/asterisk/ivr_media

і превентивно створюємо скрипт, який буде нотифікувати наш біллінг про вхідні дзвінки, що надходять /usr/local/etc/asterisk/notifybilling

# touch /usr/local/etc/asterisk/notifybilling
# chmod a+x /usr/local/etc/asterisk/notifybilling
notifybilling
#!/bin/sh
NUMBER=$*
 
BILLING_SERIAL="UBxxxxxxxxxxxxxxxxxxxxx"
BILLING_URL="http://192.168.0.161/billing/"
 
NOTIFY_URL="${BILLING_URL}?module=remoteapi&key=${BILLING_SERIAL}&action=telepony&number=${NUMBER}"
 
echo `date` ${NUMBER} >> /var/log/asterisk/income_calls.log
/usr/bin/fetch -o /dev/null ${NOTIFY_URL}

Далі переходимо до власне конфігурації нашої(го?) PBX. Усі необхідні далі нам файли конфігурації лежать у /usr/local/etc/asterisk. Для початку, згадуємо, що ми ліниві та тупі, тому ми будемо використовувати старий і нікому не потрібний chan_sip замість нового та красивого PJSIP. Для цього потрібно закоментувати рядок “noload = chan_sip.so” в modules.conf, приблизно якось так:

modules.conf
;noload = chan_sip.so

а також там же, ми можемо вимкнути деякі модулі які нам скоріш за все не знадобляться

modules.conf
noload = res_hep.so
noload = res_hep_pjsip.so
noload = res_hep_rtcp.so
noload = res_config_pgsql.so
noload = cel_sqlite3_custom.so
noload = cel_radius.so
noload = cdr_pgsql.so
noload = cdr_radius.so
noload = chan_skinny.so
noload = res_ari.so
noload = res_phoneprov.so
noload = cel_custom.so
noload = res_pjsip_phoneprov_provider.so
noload = res_ari_asterisk.so
noload = res_ari_channels.so
noload = res_ari_applications.so
noload = res_ari_device_states.so
noload = res_ari_recordings.so
noload = res_ari_sounds.so
noload = res_ari_playbacks.so
noload = res_ari_bridges.so
noload = res_ari_events.so
noload = res_ari_endpoints.so
noload = res_timing_dahdi.so
noload = res_pjsip_transport_websocket.so
noload = cel_tds.so
noload = cdr_tds.so
noload = cdr_sqlite3_custom.so
noload = chan_unistim.so

Далі редагуємо sip.conf приводячи його до наступного вигляду, і залишаючи в ньому лише якісь такі, базові штуки:

sip.conf
[general]
context=default
allowoverlap=no
bindport=5060
bindaddr=0.0.0.0
srvlookup=yes
relaxdtmf=yes
alwaysauthreject=yes
videosupport=no
notifybusy=yes
counteronpeer=yes
notifyhold=yes
notifycid=ignore-context
notifyringing=yes
pedantic=yes
callcounter=yes
register_retry_403=yes
 
[authentication]
 
[phones](!)
type=friend
context=call-out
secret=sharedsippassword
host=dynamic
nat=force_rport,comedia
qualify=yes
dtmfmode=auto
qualifyfreq=60
qualify=2000
disallow=all
allow=alaw
allow=ulaw
allow=gsm
allow=g726
allow=g729
allow=g723
allow=g722
phone-mac-type=none
call-limit=1
callgroup=1
pickupgroup=1
canreinvite=no

;==================================
; Here is some awesome phones!
;==================================
 
#include phones.conf

;==================================
; Providers configuration below
;==================================
 
#include providers.conf

Виходячи з цього, досить очевидно що для наших пірів, тобто SIP-телефонів з групи [phones], ми резервуємо окремий конфіг phones.conf і будемо використовувати загальний пароль sharedsippassword, який при бажанні можна перепризначити опцією secret конкретного клієнту. Але ж ми пам'ятаємо, що ми ліниві? Так? Власне наших SIP транків, через які надходять та виходять дзвінки, ми будемо описувати в providers.conf. На майбутнє вважатимемо їх нашими “SIP-провайдерами”. В принципі можна все це намалювати прямо в sip.conf і не використовуючи групи, як і роблять у більшості мануалів, але повірте - коли у вас буде кілька десятків телефонів і десяток транків - підтримка цього перетворитися на пекельне пекло. Воно вам треба?

Далі просто заповнюємо наші телефони у phones.conf

phones.conf
[120](phones)
callerid=Boss <120>
secret=bosspassword
 
[121](phones)
callerid=Maryana <121>
 
[122](phones)
callerid=Mariya <122>
 
[123](phones)
callerid= Markiyan <123>

Та наших SIP-провайдерів відповідно в providers.conf

providers.conf
; Ukrtelecom 0800
[0333333333]
type=peer
defaultuser=0333333333
secret=
fromuser=0333333333
host=195.5.0.54
port=5060
context=call-in
fromdomain=195.5.0.54
language=ru-ru
nat=never
qualifyfreq=60
qualify=2000
directmedia=no
insecure=port,invite
dtmfmode=rfc2833
disallow=all
allow=alaw
 
 
;Zadarma trunk
[444444]
host=sip.zadarma.com
insecure=invite,port
type=peer
fromdomain=sip.zadarma.com
disallow=all
allow=alaw
dtmfmode=auto
secret=zadarmasecretpassword
defaultuser=444444
trunkname=444444
fromuser=444444
callbackextension=444444
context=call-in
qualify=400
directmedia=no
nat=force_rport,comedia

Додаємо телефони нашої техпідтримки в чергу для обдзвонювання, приводячи queues.conf до наступного виду:

queues.conf
;Primary tech support queue
[techsupport]
music = dasmusic
timeout=7
wrapuptime=5
ringinuse=yes
autofill=yes
periodic-announce = /usr/local/etc/asterisk/ivr_media/wait
periodic-announce-frequency = 15

;possible strats: ringall, leastrecent, fewestcalls, random, rrmemory, linear, wrandom
strategy = rrmemory

;Queue members here
member => SIP/121
member => SIP/122
member => SIP/123

та додаємо відповідний клас музики додаючи у musiconhold.conf наступне:

musiconhold.conf
[dasmusic]
mode=quietmp3
directory=/usr/local/etc/asterisk/ivr_media/dasmusic

Все досить очевидно, так? А тепер намагаємось зосередитись. Зараз почнеться трохи складніше.
Описуємо поведінку всієї нашої телефонії у вигляді діалплану, приводячи extensions.conf до наступного вигляду

extensions.conf
[general]
static=yes
writeprotect=no
 
[globals]
DIR_RECORDS=/mnt/calls/
 
[default]
 
[recording-in]
exten => s,1,Set(fname=in_${ARG1}_${STRFTIME(${EPOCH},,%Y-%m-%d-%H-%M-%S)})
exten => s,n,Set(CDR(filename)=${fname}.gsm)
exten => s,n,Set(CDR(userfield)=in)
exten => s,n,MixMonitor(${DIR_RECORDS}${fname}.gsm,b)
exten => s,n(no),Verbose(Exit record)
exten => s,n,Return()
 
[recording-out]
exten => s,1,Set(fname=out_${ARG2}_${STRFTIME(${EPOCH},,%Y-%m-%d-%H-%M-%S)})
exten => s,n,Set(CDR(filename)=${fname}.gsm)
exten => s,n,Set(CDR(userfield)=out)
exten => s,n,MixMonitor(${DIR_RECORDS}${fname}.gsm,b)
exten => s,n(no),Verbose(Exit record)
exten => s,n,Return()
 
 
[handup-sip]
exten => _X!,1,HangUp()

; Outcoming calls
[call-out]

;Debug and testing extensions
exten => 334,1,Goto(ivr-main,s,1)
exten => 333,1,Queue(techsupport,t)

; internal num call
exten => _XXX,1,Dial(SIP/${EXTEN})

; external number call via 0800
exten => _XXX.,1,Set(VOLUME(RX)=8)
exten => _XXX.,2,Set(VOLUME(RX)=8)
exten => _XXX.,3,GoSub(recording-out,s,1,(${CALLERID(num)},${EXTEN}))
exten => _XXX.,4,Dial(SIP/${EXTEN}@0333333333)

;zadarma test
exten => 1111,1,Dial(SIP/${EXTEN}@444444)
 
include => handup-sip

;Incoming calls
[call-in]
exten => 0333333333,1,Goto(ivr-main,s,1)
exten => 444444,1,Goto(ivr-main,s,1)
 
 
[ivr-main]
exten => s,1,Answer()
exten => s,n,Set(VOLUME(TX)=8)
exten => s,n,Set(VOLUME(RX)=8)
;comment following line to disable nightmode
exten => s,n,GotoIfTime(20:00-08:00,*,*,*?nightmode,s,1)
exten => s,n,GoSub(notifybilling,s,1,(${CALLERID(num)}))
exten => s,n,Wait(3)
exten => s,n,Background(/usr/local/etc/asterisk/ivr_media/greeting)
exten => s,n,GoSub(recording-in,s,1,(${CALLERID(num)},${EXTEN}))
exten => s,n,Queue(techsupport,t)
 
 
[nightmode]
exten => s,1,Wait(2)
exten => s,2,Playback(/usr/local/etc/asterisk/ivr_media/nighttime)
exten => s,3,Wait(3)
exten => s,4,Hangup()
 
[notifybilling]
exten => s,1,system(/usr/local/etc/asterisk/notifybilling ${ARG1})
exten => s,n,Return()

Детальніше про діалплани та те як вони працюють, ви можете дізнатись, почитавши ось цю документацію чи подивившись ось ці, дуже цікаві та пізнавальні відео на YouTube.

Стало страшно? Ну якщо так - можете помолитись і продовжувати читати далі

У випадку, якщо вам надто складно, то все що вам потрібно знати, це те що вхідні дзвінки маршрутизуються в контексті (так, це оті штуки в квадратних дужечках) call-in та передають дзвінок в контекст ivr-main якоюсь отакою конструкцією

[call-in]
exten => номер_на_котрий_прилетів_дзвінок,1,Goto(ivr-main,s,1)

а те, куди буде змаршрутизовано вихідні дзвінки з ваших телефонів керується в контексті call-out. Власне за напрямок за замовчуванням, кудою будуть улітати всі наші вихідні звінки на номери довжиною більше трьох цифр відповідає оця конструкція:

[call-out]
.....
exten => _XXX.,4,Dial(SIP/${EXTEN}@0333333333)

Окей, страшне закінчилось. Продовжуємо далі.

Вмикаємо запис CDR в нашу MySQL базу, додавши в конфіг cdr_mysql.conf секцію [global] наступного вигляду

cdr_mysql.conf
[global]
hostname=localhost
dbname=asterisk
table=cdr
user=asterisk
password=asteriskmysqlpassword

Також не забуваємо переконатися, що MySQL буде слухати всі потрібні нам інтерфейси, виправивши опцію bind-address у секції [mysqld] конфігу /usr/local/etc/mysql/my.cnf якось так

my.cnf
bind-address = 0.0.0.0

з подальшим перезапуском MySQL

# service mysql-server restart

Тепер можемо перевірити, як це все стартує запустивши Asterisk

# service asterisk start

і залогінившись у його консоль

# asterisk -r

далі ми можемо виконати, наприклад, команду sip show peers і дізнатися як виглядають наші піри

sip*CLI> sip show peers
Name/username             Host                                    Dyn Forcerport Comedia    ACL Port     Status      Description                      
0333333333/0333333333     195.5.0.54                                  No         No             5060     OK (14 ms)                                  
120                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
121                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
122                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
123                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
444444/444444             185.45.152.161                              Yes        Yes            5060     OK (29 ms)                                   

Наразі, ми можемо взяти будь-який підручний SIP-клієнт чи телефон, та швиденько його налаштувати

і переконатися, що він успішно логіниться.

sip*CLI> sip show peers
Name/username             Host                                    Dyn Forcerport Comedia    ACL Port     Status      Description                      
0333333333/0333333333     195.5.0.54                                  No         No             5060     OK (14 ms)                                  
120                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
121                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
122/122                   172.16.42.8                              D  Yes        Yes            5060     OK (5 ms) 
123                       (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
444444/444444             185.45.152.161                              Yes        Yes            5060     OK (29 ms)                                   

Також можна подивитися на стан нашої черги за допомогою команди queue show

sip*CLI> queue show 
techsupport has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0%, SL2:0.0% within 0s
   Members: 
      SIP/121 (ringinuse enabled) (Not in use) has taken no calls yet (login was 6 secs ago)
      SIP/123 (ringinuse enabled) (Unavailable) has taken no calls yet (login was 6 secs ago)
      SIP/122 (ringinuse enabled) (Not in use) has taken no calls yet (login was 6 secs ago)
   No Callers

Тепер можна перезавантажити сервер, щоб переконатися, що все стартує саме і нормально працює після його завантаження

# reboot

Тестуємо

Наразі, ми можемо спробувати зателефонувати на номер 1111 через Zadarma, щоб дізнатися про стан нашого рахунку і просто послухати як воно звучить. А також спробувати зателефонувати до черги самому, скориставшись тестовим номером 334 аби послухати як це все звучатиме для користувачів при вхідному дзвінку.

Коротко про озвучку та формати

Ми ж хочемо, щоб усе гарно розмовляло, вітало та повідомляло? Для початку слід запам'ятати, що всі файли з нашим озвученням ми будемо класти в /usr/local/etc/asterisk/ivr_media/ у прийнятному для Asterisk форматі. Конвертувати MP3 в нього, можна якось так:

$ lame --decode filename.mp3 tmp.wav
$ sox -v 0.5 tmp.wav -t wav -b 16 -r 8000 -c 1 filename.wav
$ rm tmp.wav

Виходячи з вищеописаного прикладу конфігурації ми припускаємо, що такі файли містять відповідну озвучку:

  • greeting.wav - початкове вітання типу “Вас вітає провайдер ХХХ, з метою забезпечення якості обслуговування всі дзвінки записуються, очікуйте з'єднання з оператором”
  • nighttime.wav - озвучка нічного режиму, типу “Вибачте, ви зателефонували в неробочий час, але ми обов'язково вам перетелефонуємо”
  • wait.wav - періодичне оповіщення під час очікування в черзі, щось типу “очікуйте з'єднання з оператором”
  • ivr_media/dasmusic/*.mp3 - якась музика очікування, яка може бути в mp3.

Якщо ви з якоїсь причини, не здатні за досить мало грошей домовитися з професійним диктором, який надиктує потрібні вам звукові файли з нормальною артикуляцією та поставленим голосом, можете спробувати використати щосьіз цих файлів, за авторством VikDon чисто для тестування.

Записи дзвінків, зберігаємо в .gsm, оскільки місце в вас не безлімітне, а Ubilling вміє сам нормально прослуховувати та конвертувати при збереженні їх в mp3 чи ogg.

Трохи про стратегії обдзвону

Те, в якій черговості будуть дзвонити телефони вашої техпідтримки регулюється опцією strategy черги в конфігу queues.conf. Вони можуть бути якимись такими:

  • linear - телефони дзвонять в порядку своєї наявності в черзі “зверху вниз”.
  • ringall - одночасно дзвонять всі телефони, всі бігають і панікують.
  • leastrecent - виклики надходять спочатку на ті номери, котрі найдовше не приймали викликів.
  • fewestcalls - виклик надходить на номери, котрі прийняли менше всього викликів.
  • random - дзвінки надходять на випадкові номери.
  • rrmemory - телефони дзвонять циклічно, по колу, починаючи з наступного телефону після того, хто останнім відповідав на виклик.
  • wrandom - звонить випадковий телефон, але використовується штраф цього номеру в якості ваги для розрахунку метрики.

Переходимо до налаштувань Ubilling

Монтуємо записи дзвінків на локальну файлову систему:

# mkdir /mnt/calls_records 
# mkdir /mnt/calls_archive
# chmod -R 777 /mnt/calls_*
# mount 192.168.0.162:/mnt/calls /mnt/calls_records

Додаємо автоматичне монтування цієї директорії при завантаженні в /etc/fstab

192.168.0.162:/mnt/calls /mnt/calls_records nfs rw   0  0

Далі в alter.ini вмикаємо власне телефонію а також заповнюємо доступ до БД з CDR:

alter.ini
TELEPONY_ENABLED=1
TELEPONY_CDR="192.168.0.162|asterisk|asteriskmysqlpassword|asterisk|cdr"

Вмикаємо модуль “Записи телефонних розмов”

alter.ini
PBXMON_ENABLED=1

Модуль “Навіщо телефонуєш?”

alter.ini
WDYC_ENABLED=1

та додаємо потрібні для його роботи виклики в crontab

*/1 * * * *     /bin/ubapi "whydoyoucall"
5 20 * * *     /bin/ubapi "whydoyoucallstats"

Він нам потрібен для відслідковування “пропущених дзвінків”, ну тобто “абонент зателефонував, повисів на лінії, йому стало сумно, він поклав слухавку”. В самому по собі “пропущенному дзвінку” немає нічого страшного. Набагато гірше, коли він в кінці робочого дня стає “дзвінком без реакції” бо абоненту ніхто не перетелефонував і не дізнався, що він хотів. Власне для забезпечення цієї самої реакції нам і потрібен модуль “Навіщо телефонуєш?”.

Та вмикаємо модуль “Історія дзвінків”

alter.ini
CALLSHIST_ENABLED=1

Швиденько також налаштовуємо модуль По кому подзвін?

alter.ini
FWTBT_ENABLED=1
FWTBT_ANYWHERE=1
FWTBT_ADMINS="maryana,mariya,markiyan"
FWTBT_INTERVAL=7
FWTBT_TIMER=10
FWTBT_DESKTOP=1

Також може знадобитись “Телефонний довідник”

alter.ini
PHONEBOOK_ENABLED=1

де ми, щонайменше зможемо заповнити внутрішні номери наших працівників

Також непоганим кейсом, задля того аби зробити ваш сервіс ще кращим, може буде налаштувати модуль та оточення для обробки запитів зворотніх дзвінків:

alter.ini
CALLMEBACK_ENABLED=1

Також чисто заради естетичного задоволення, можемо додати маунтпоінт записів дзвінків до опції SYSLOAD_DISKS

alter.ini
SYSLOAD_DISKS="/,/mnt/calls_records/"

задля того, щоб візуально контролювати заповненість

Ось власне і все.

Що працює після цього всього?

Тепер, при надходженні вхідного дзвінка, ваша техпідтримка зможе:

  • Побачити що їм телефонують за допомогою модулю По кому подзвін? та швиденько перейти до профілю абонента прямо з сповіщення.
  • Опрацювати (вочевидь перетелефонувавши їм) пропущені дзвінки абонентів, за допомогою модулю “Навіщо телефонуєш”?
  • Опрацювати запити на зворотній дзвінок, отримані скажімо з вашого сайтку за допомогою модулю “Перетелефонуйте мені будь ласка”.
  • Дізнатись хто намагався зателефонувати в неробочий час та взнати “якого біса ти хотів?” за допомогою тих же модулів “ТелеПоні” чи “Навіщо телефонуєш”?
  • Прямо з профілю абонента, дізнатись коли та скільки він телефонував, та прослухати записи попередніх розмов з ним скориставшись Чорною магією.

Менеджмент, в свою чергу також може контролювати, базові KPI опрацювання телефонних дзвінків техпідтримкою, за допомогою модулю “Екзистенційний кінць” куди вже автоматично складаються дані по наступних показниках:

  • Кількість вхідних дзвінків
  • Кількість вхідних дзвінків з відповіддю
  • Кількість вхідних дзвінків на які не відповіли “одразу”.
  • Загальна тривалість розмов
  • Середня тривалість розмови
  • Відсоток вхідних дзвінків, на котрі відповіли “одразу”.
  • Відсоток дзвінків без реакції. Тобто відсоток “повністю пропущених” дзвінків куди не передзвонили.
  • Час реакції на пропущені дзвінки. Власне інтервал часу між “абонент позвонив, не дочекався, поклав слухавку” і “ми його набрали”.

Ну а також вибірково прослуховувати/завантажувати записи телефонних розмов у різних форматах, для розбору польотів.

Телепатична реакція на стан абонента

Вам також, може захотітись автоматично реагувати на стан ваших абонентів, у випадку якщо вам телефонує ваш абонент з відомим вам номером у якого на рахунку заборгованість “одразу після привітання кажемо йому “шановний абонент у вас на рахунку заборгованість”, або його рахунок заморожено, про що ми також хочемо його повідомити. Ну або ще щось на кшталт того. Тут на допомогу нам прийде механіка AGI скриптів, котру ми можемо викликати з нашого контексту ivr-main. Взагалі, якщо ви розумієте, що ви робите, насправді, все лімітовано тільки вашою фантазією та скіллом.

Для початку встановлюємо PHP, на якому ми і будемо писати AGI скрипти, котрі лежатимуть у нас за шляхом /usr/local/share/asterisk/agi-bin/

# pkg install -y php82

Після чого, створюємо наступний файл скрипта /usr/local/share/asterisk/agi-bin/telepathy.php який власне і отримуватиме стан вгаданого за номером абонента, паралельно нотифікуючи біллінг про вхідний дзвінок.

telepathy.php
#!/usr/local/bin/php -q
<?php
 
/**
 * Config section
 */
 
//Ubilling serial number
$ubillingSerial = 'UBxxxxxxxxxxxxxxxxxxxxx';
//Full Ubilling URL for API connection
$ubillingApiUrl = 'http://192.168.0.161/billing/';
 
$userStates = array(
    '2' => 'nomoney',
    '3' => 'frozen'
);
 
/**
 * End of config section
 */
 
$stdin = fopen('php://stdin', 'r');
$stdout = fopen('php://stdout', 'w');
 
$number=$argv[1];
 
$url = $ubillingApiUrl . '?module=remoteapi&key=' . $ubillingSerial . '&action=telepony&number=' . $number;
$user = file_get_contents($url);
$user = trim($user);
if (isset($userStates[$user])) {
//uncomment following line to debug detected caller id user state
//fputs($stdout,'SAY ALPHA "'.$userStates[$user].'" ""'.PHP_EOL);
fputs($stdout,'EXEC PLAYBACK "/usr/local/etc/asterisk/ivr_media/'.$userStates[$user].'" ""'.PHP_EOL);
fflush($stdout);
}
 
 
fclose ($stdin);
fclose ($stdout);
exit(0);

додаємо контекст telepathy котрий власне і буде викликати наш AGI скрипт з параметром у вигляді CALLERID(num)

extensions.conf
[telepathy]
exten => s,1,AGI(telepathy.php,${ARG1})
exten => s,n,Return()

ну і власне, наш контекст ivr main в діалплані, тепер може виглядати наступним чином:

extensions.conf
[ivr-main]
exten => s,1,Answer()
exten => s,n,Set(VOLUME(TX)=8)
exten => s,n,Set(VOLUME(RX)=8)
;comment following line to disable nightmode
exten => s,n,GotoIfTime(20:00-08:00,*,*,*?nightmode,s,1)
exten => s,n,Wait(3)
exten => s,n,Background(/usr/local/etc/asterisk/ivr_media/greeting)
exten => s,n,GoSub(telepathy,s,1,(${CALLERID(num)}))
exten => s,n,GoSub(recording-in,s,1,(${CALLERID(num)},${EXTEN}))
exten => s,n,Queue(techsupport,t)

власне очевидно, що ми заміняємо контекст notifybilling на telepathy для того, щоб здійснювати нотифікацію біллінгу про вхідний дзвінок а також озвучувати абоненту якийсь файл, з /usr/local/etc/asterisk/ivr_media/ відносно його статусу, перед передачею дзвінка до черги.

Коротко про статуси абонентів, що повертаються в AGI скрипт:

  • 0 - невідомий нам номер (абонента не знайдено)
  • 1 - абонента знайдено, з рахунком якого все добре
  • 2 - абонента знайдено, на його рахунку, існує заборгованість
  • 3 - абонента знайдено, його рахунок заморожено

Отож, виходячи з цього, наступним массивом AGI скрипта телепатії, регулюється який конкретний файл з теки, буде програно абоненту одразу після привітання:

$userStates = array(
    '0' => 'nouser',
    '1' => 'allok',
    '2' => 'nomoney',
    '3' => 'frozen'
);

очевидно, що на відповідні статуси буде програно файли з іменами nouser.wav, allok.wav, nomoney.wav та frozen.wav які ми покладемо у /usr/local/etc/asterisk/ivr_media/?

Також ми можемо зручно віддебажити виконання нашого контексту та AGI скрипта за допомогою команди agi set debug on в консолі Asterisk:

# asterisk -r
*CLI> agi set debug on
AGI Debugging Enabled

Та зателефонувавши за тестовим номером 334, нашого контексту ivr-main. Якось так:

<SIP/122-00000007>AGI Tx >> agi_request: telepathy.php
<SIP/122-00000007>AGI Tx >> agi_channel: SIP/122-00000007
<SIP/122-00000007>AGI Tx >> agi_language: en
<SIP/122-00000007>AGI Tx >> agi_type: SIP
<SIP/122-00000007>AGI Tx >> agi_uniqueid: 1677860146.8
<SIP/122-00000007>AGI Tx >> agi_version: 18.15.1
<SIP/122-00000007>AGI Tx >> agi_callerid: 122
<SIP/122-00000007>AGI Tx >> agi_calleridname: Mariya
<SIP/122-00000007>AGI Tx >> agi_callingpres: 0
<SIP/122-00000007>AGI Tx >> agi_callingani2: 0
<SIP/122-00000007>AGI Tx >> agi_callington: 0
<SIP/122-00000007>AGI Tx >> agi_callingtns: 0
<SIP/122-00000007>AGI Tx >> agi_dnid: 334
<SIP/122-00000007>AGI Tx >> agi_rdnis: unknown
<SIP/122-00000007>AGI Tx >> agi_context: telepathy
<SIP/122-00000007>AGI Tx >> agi_extension: s
<SIP/122-00000007>AGI Tx >> agi_priority: 1
<SIP/122-00000007>AGI Tx >> agi_enhanced: 0.0
<SIP/122-00000007>AGI Tx >> agi_accountcode: 
<SIP/122-00000007>AGI Tx >> agi_threadid: 34418519040
<SIP/122-00000007>AGI Tx >> agi_arg_1: 122
<SIP/122-00000007>AGI Tx >> 
<SIP/122-00000007>AGI Rx << EXEC PLAYBACK "/usr/local/etc/asterisk/ivr_media/frozen" ""
<SIP/122-00000007>AGI Tx >> 200 result=0

Чорний список

Дуже-дуже чорний. Початок нашого контексту ivr-main повинен виглядати наступним чином:

[ivr-main]
exten => s,1,Answer()
exten => s,2,GotoIf($[${BLACKLIST()}=1]?blacklist)
exten => s,3,GoTo(ivr-main,s,5)
exten => s,4(blacklist),Hangup()

Додавання номера в чорний список відбувається так:

asterisk -rx 'database put blacklist 0931234567 1'
asterisk -rx 'database del blacklist 0931234567'

Перегляд чорного-чорного списку номерів:

asterisk -rx 'database show blacklist'

Конференції

Налаштування конференцій, теж дуже просте та зрозуміле. Для початку в діалплан, в контекст call-out необхідно додати відповідні записи, якось так:

extensions.conf
; Outcoming calls
[call-out]
; conference
exten => 777,1,Answer()
exten => 777,n,ConfBridge(1,confer)
 
....

та у конфіг /usr/local/etc/asterisk/confbridge.conf, в самому його кінці, необхідно додати якусь таку секцію налаштувань нашої конференції:

confbridge.conf
[confer]
type=bridge
max_members=20
mixing_interval=10
internal_sample_rate=auto
record_conference=yes

Очевидно, що наші телефони, одночасно всі, зможуть між собою поспілкуватись, зідзвонившись за номером 777.

telepony.txt · Востаннє змінено: 2024/02/06 13:39 повз nightfly