
В нашей организации используется ip телефония на базе Trixbox (по сути тот же FreePBX с некоторыми отличиями), а также телефонные апараты фирмы Polycom. С каждым днем штат компании рос и стало все тяжелее запоминать кучу внутренних номеров сотрудников. Часть сотрудников начала вручную вбивать адресную книгу в телефоне, но большая ее половина тратила тонны бумаги на распечатку очередного измененного справочника, а также еще больше времени на поиски нужного номера. С этим нужно было что то делать.
Все телефоны получают свою конфигурацию через tftp сервер, туда и полезем. Обнаружилось что при загрузке, телефон проверяет наличие *macaddr*-directory.xml в директории *tftpserver_dir*/polycom/contacts/, и подгружает его если находит. Этим и воспользуемся.
Сформируем план действий:
- Формирование файла xml с контактами. Чтобы не городить сервисы, надо добиться формирования через bash скрипты.
- Получать информацию о существующих телефонах нужно из CLI asterisk. #Проблема №1.
- Загрузка справочников, путем перезагрузки телефонов 1 раз в сутки ночью.
trixbox1*CLI> sip show peer 114 trixbox1*CLI> * Name : 114 Secret : <Set> MD5Secret : <Not set> Context : from-internal Subscr.Cont. : <Not set> Language : ru AMA flags : Unknown Transfer mode: open CallingPres : Presentation Allowed, Not Screened Callgroup : Pickupgroup : Mailbox : 114@device VM Extension : *97 LastMsgsSent : 0/0 Call limit : 50 Dynamic : Yes Callerid : "device" <114> MaxCallBR : 384 kbps Expire : 1410 Insecure : no Nat : Always ACL : Yes T38 pt UDPTL : No CanReinvite : No PromiscRedir : No User=Phone : No Video Support: Yes Trust RPID : No Send RPID : No Subscriptions: Yes Overlap dial : Yes DTMFmode : rfc2833 LastMsg : 0 ToHost : Addr->IP : 192.168.0.95 Port 5060 Defaddr->IP : 0.0.0.0 Port 5060 Def. Username: 114 SIP Options : (none) Codecs : 0x28000c (ulaw|alaw|h263|h264) Codec Order : (ulaw:20,alaw:20) Auto-Framing: No Status : OK (18 ms) Useragent : PolycomSoundPointIP-SPIP_321-UA/3.1.3.0507 Reg. Contact : sip:114@192.168.0.95
Нас интересует строка Callerid: «device» <114> Вместо информации о CallerID (ФИО) сотрудника мы видим злополучное «device».
Решить можно двумя способами. Первый найти в базе MySQL где хранит информацию по CallerID и на лету при формировании XML получать данные через запросы. Либо вторым менее трудоемким и менее ресурсоемким.
Зная что trixbox целиком и полностью на php мы можем попытаться найти в исходных кодах где же trixbox пишет это «device». Поковырявшись немного в /var/www/ находим файлик /var/www/html/admin/modules/core/functions.inc.php с очень интересным комментарием разработчиков.
// Very bad $iaxfields[] = array($account,'account',$account); $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
Не будем думать и искать откуда разработчики берут этот description, при создании extension обязательное поле Display name и как раз туда мы вносим ФИО сотрудника, исходя из этого подправим немного файлик.
Не забываем про бекап файла вдруг что пойдет не так или лишнее зацепим, и да не следует это делать сразу на боевом сервере.
Меняем в строке
$_REQUEST['description']
на
$_REQUEST['name']
получаем:
$sipfields[] = array($account,'callerid',(isset($_REQUEST['name']) && $_REQUEST['name'])?$_REQUEST['name']." <".$account.'>':'device'." <".$account.'>');
Сохраняем, идем в веб и пересохраняем extension.
Заходим в CLI asterisk смотрим и радуемся:
trixbox1*CLI> sip show peer 114 trixbox1*CLI> * Name : 114 Secret : <Set> MD5Secret : <Not set> Context : from-internal Subscr.Cont. : <Not set> Language : ru AMA flags : Unknown Transfer mode: open CallingPres : Presentation Allowed, Not Screened Callgroup : Pickupgroup : Mailbox : 114@device VM Extension : *97 LastMsgsSent : 0/0 Call limit : 50 Dynamic : Yes Callerid : "Ivan Petrov" <114> MaxCallBR : 384 kbps Expire : 1410 Insecure : no Nat : Always ACL : Yes T38 pt UDPTL : No CanReinvite : No PromiscRedir : No User=Phone : No Video Support: Yes Trust RPID : No Send RPID : No Subscriptions: Yes Overlap dial : Yes DTMFmode : rfc2833 LastMsg : 0 ToHost : Addr->IP : 192.168.0.95 Port 5060 Defaddr->IP : 0.0.0.0 Port 5060 Def. Username: 114 SIP Options : (none) Codecs : 0x28000c (ulaw|alaw|h263|h264) Codec Order : (ulaw:20,alaw:20) Auto-Framing: No Status : OK (18 ms) Useragent : PolycomSoundPointIP-SPIP_321-UA/3.1.3.0507 Reg. Contact : sip:114@192.168.0.95
Проблема решена, осталось пройти только по всем extension и пересохранить их, чтобы trixbox переписал конфиг файлы с правильным caller id.
Идем далее.
Научим asterisk удаленно перегружать телефоны Polycom. Для этого в файлик /etc/asterisk/sip_notify.conf добавляем следующие строки:
[polycom-check-cfg] Event=>check-sync Content-Length=>0
Рестартим asterisk.
После этого если в CLI asterisk выполнить
sip notify polycom-check-cfg 114
телефонный апарат Polycom на котором зарегистрирован extension 114 перезагрузится.
Далее получим список зарегистрированных телефонов, он нам нужен для их удаленной перезагрузки
asterisk -rx 'sip show peers'
получаем
354/354 192.168.0.226 D N A 5060 OK (19 ms) 353/353 192.168.0.108 D N A 5060 OK (15 ms) 352 (Unspecified) D N A 0 UNKNOWN 351 (Unspecified) D N A 0 UNKNOWN 342/342 192.168.0.138 D N A 5061 OK (7 ms) 341/341 192.168.0.138 D N A 5060 OK (7 ms)
C помощью grep уберем лишнее (нас интересуют только апараты зарегистрированные на текущий момент они в списке со статусом «ОК» и отделяем только номера телефонов)
asterisk -rx 'sip show peers' |grep OK |awk '{print $1}'|awk -F'/' '{print $1}'
получаем
400 363 362 361 359 357 356 355 354 353 342
Направляем полученный результат во временный файл оттуда будет проще читать построчно.
asterisk -rx 'sip show peers' |grep OK |awk '{print $1}'|awk -F'/' '{print $1}' > numbers.txt
В данном списке мы получили те телефоны которые надо будет перезагрузить и подгрузить в них справочник.
Вторым заходом формируем сам xml файл справочник (снова исключая ненужное) и пишем в файлик.
asterisk -rx 'sip show peers' |egrep 'OK|UNKNOWN' |grep -v 'GSM' > extensions.txt
Caller id получаем следующим образом
asterisk -rx 'sip show peer 114' |grep Callerid
Далее нам нужно построчно читая extensions.txt получать caller id и писать в файлик формируя на лету куски xml.
Для начала сформируем эталонный 000000000000-directory.xml он загружается телефонами по умолчанию только 1 раз при первой загрузке телефона, далее в папке /tftpboot/polycom/contacts/ формируется файл macaddress-directory.xml который в дальнейшем и будет постоянно подгружаться (тут надо не забыть после формирования эталонного файла заменять им текущие чтобы те подгрузились в телефон). Так как это xml нужны заголовки и структура которую понимает телефон. Набираем:
echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' > 000000000000-directory.xml echo '<!-- $RCSfile$ $Revision: 35928 $ -->' >> 000000000000-directory.xml echo '<directory>' >> 000000000000-directory.xml echo ' <item_list>' >> 000000000000-directory.xml
Заметьте последняя строка с табуляцией, чтобы файл был красивым при формировании, и структурированным.
Далее цикл чтения extensions.txt
cat extensions.txt | while read line do
Во первых избавляемся от всего лишнего (факсов, free extensinons, запасных номеров начинающихся с 1000х и т.д.)
RES=$(asterisk -rx "sip show peer $line" |grep Callerid |grep -v 'Free' |grep -v 'free' |grep -v 'fax' |grep -v '1000' |grep -v 'device' |grep -v 'FAX' |grep -v 'Test'); if [ "$RES" != "" ]; then
и тут уже формируем красивый кусок кода xml
asterisk -rx "sip show peer $line" |grep Callerid | awk -F': "' '{print $2}' | awk -F'" <' '{print \ "\t\t<item>\n\t\t\t<ln>"$1"</ln>\n\t\t\t<ct>"$2"</ct>\n\t\t</item>"}' >> 000000000000-directory.xml
пример
<item> <ln>Ivan Petrov</ln> <ct>114></ct> </item>
ну и дописываем структуру xml
echo ' </item_list>' >> 000000000000-directory.xml echo '</directory>' >> 000000000000-directory.xml
Полный код формирования xml файла:
echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' > 000000000000-directory.xml echo '<!-- $RCSfile$ $Revision: 35928 $ -->' >> 000000000000-directory.xml echo '<directory>' >> 000000000000-directory.xml echo ' <item_list>' >> 000000000000-directory.xml cat extensions.txt | while read line do RES=$(asterisk -rx "sip show peer $line" |grep Callerid |grep -v 'Free' |grep -v 'free' |grep -v 'fax' |grep -v '1000' |grep -v 'device' |grep -v 'FAX' |grep -v 'Test'); if [ "$RES" != "" ]; then asterisk -rx "sip show peer $line" |grep Callerid | awk -F': "' '{print $2}' | awk -F'" <' '{print \ "\t\t<item>\n\t\t\t<ln>"$1"</ln>\n\t\t\t<ct>"$2"</ct>\n\t\t</item>"}' >> 000000000000-directory.xml fi done echo ' </item_list>' >> 000000000000-directory.xml echo '</directory>' >> 000000000000-directory.xml
У всех апаратов Polycom mac-адрес начинается с 00:04:F, отсюда можно в сети найти все телефоны через arp
arp -a |grep 00:04:F |awk '{print $4}' > mac.txt
по циклу копируем 000000000000-directory.xml в macaddress-directory.xml
cat mac.txt |while read phonemac do MAC=${phonemac//:/}; #регулярка для того чтобы убрать ":" из строки cp /tftpboot/polycom/contacts/000000000000-directory.xml /tftpboot/polycom/contacts/$MAC-directory.xml done
Ну и почти финишная прямая по циклу из файла numbers.txt полученного вначале ребутаем телефоны:
cat numbers.txt |while read number do asterisk -rx "sip notify polycom-check-cfg $number" done
Полный код скрипта:
#!/bin/sh asterisk -rx 'sip show peers' |grep OK |awk '{print $1}'|awk -F'/' '{print $1}' > numbers.txt asterisk -rx 'sip show peers' |egrep 'OK|UNKNOWN' |grep -v 'GSM' |awk '{print $1}'|awk -F'/' '{print $1}' > extensions.txt arp -a |grep 00:04:F |awk '{print $4}' > mac.txt echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' > 000000000000-directory.xml echo '<!-- $RCSfile$ $Revision: 35928 $ -->' >> 000000000000-directory.xml echo '<directory>' >> 000000000000-directory.xml echo ' <item_list>' >> 000000000000-directory.xml cat extensions.txt | while read line do RES=$(asterisk -rx "sip show peer $line" |grep Callerid |grep -v 'Free' |grep -v 'free' |grep -v 'fax' |grep -v '1000' |grep -v 'device' |grep -v 'FAX' |grep -v 'Test'); if [ "$RES" != "" ]; then asterisk -rx "sip show peer $line" |grep Callerid | awk -F': "' '{print $2}' | awk -F'" <' '{print "\t\t<item>\n\t\t\t<ln>"$1"</ln>\n\t\t\t<ct>"$2"</ct>\n\t\t</item>"}' >> 000000000000-directory.xml fi done echo ' </item_list>' >> 000000000000-directory.xml echo '</directory>' >> 000000000000-directory.xml cat mac.txt |while read phonemac do MAC=${phonemac//:/}; cp /tftpboot/polycom/contacts/000000000000-directory.xml /tftpboot/polycom/contacts/$MAC-directory.xml done cat numbers.txt |while read number do asterisk -rx "sip notify polycom-check-cfg $number" done rm numbers.txt rm extensions.txt rm mac.txt rm 000000000000-directory.xml
Сохраняем скрипт в папке /etc/cron.daily и после этого каждую ночь все изменения будут загружаться в телефонный справочник настольного телефона с возможностью быстрого поиска по нему. Пользователи довольны, бумага в офисе зря не переводится.
ссылка на оригинал статьи http://habrahabr.ru/post/211606/
Добавить комментарий