Загрузка телефонной книги в IP телефоны фирмы Polycom

от автора


В нашей организации используется ip телефония на базе Trixbox (по сути тот же FreePBX с некоторыми отличиями), а также телефонные апараты фирмы Polycom. С каждым днем штат компании рос и стало все тяжелее запоминать кучу внутренних номеров сотрудников. Часть сотрудников начала вручную вбивать адресную книгу в телефоне, но большая ее половина тратила тонны бумаги на распечатку очередного измененного справочника, а также еще больше времени на поиски нужного номера. С этим нужно было что то делать.
Все телефоны получают свою конфигурацию через tftp сервер, туда и полезем. Обнаружилось что при загрузке, телефон проверяет наличие *macaddr*-directory.xml в директории *tftpserver_dir*/polycom/contacts/, и подгружает его если находит. Этим и воспользуемся.

Сформируем план действий:

  1. Формирование файла xml с контактами. Чтобы не городить сервисы, надо добиться формирования через bash скрипты.
  2. Получать информацию о существующих телефонах нужно из CLI asterisk. #Проблема №1.
  3. Загрузка справочников, путем перезагрузки телефонов 1 раз в сутки ночью.
Проблема №1

По умолчанию trixbox при записи информации в конфиг файлы asterisk, не пишет никуда caller id, а хранит их только у себя в mysql базе. Исходя из этого мы видим следующую картину:

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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *