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

в 8:38, , рубрики: asterisk, freepbx, linux, Polycom, tutorial, метки: , , ,

Загрузка телефонной книги в 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 
"tt<item>nttt<ln>"$1"</ln>nttt<ct>"$2"</ct>ntt</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 
"tt<item>nttt<ln>"$1"</ln>nttt<ct>"$2"</ct>ntt</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 "tt<item>nttt<ln>"$1"</ln>nttt<ct>"$2"</ct>ntt</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 и после этого каждую ночь все изменения будут загружаться в телефонный справочник настольного телефона с возможностью быстрого поиска по нему. Пользователи довольны, бумага в офисе зря не переводится.

Автор: albertxyc

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js