Удаленная адресная книга (Address-book)
Описание
Данный сервис позволяет поддерживать удаленную книгу Yealink, GrandStream, Cisco и ТА других производителей которую возможно получать либо из базы абонентов SSW (по http|https), либо по протоколу ldap, либо с адресной книги ECSS-10 (используя mysql).
На текущий момент:
- Из базы абонентов ssw можно получить: имя и номер;
- По протоколу ldap можно получить: имя, номер, почту;
- Используя mysql: имя, номер, почту(почта только по протоколу CardDAV ).
Конфигурация сервиса
Настройка сервиса
Заранее нужно определиться из какого источника будет осуществляться получение данных абонентов.
- Если данные будут получены по ldap, необходимо чтобы на момент настройки был доступ к развернутому ldap серверу (сторонний сервер).
- Если абонентские номера будут получены через mysql, то необходимо иметь доступ до сервера mysql, который используется ECSS-10 (по умолчанию при установке пакета ecss-mysql создается специальный пользователь address_book с доступом до таблицы address_book). При этом, если будет использован другой пользователь mysql, необходимо убедиться, что у него есть доступ до базы address_book.
- Если номера абонентов будут получены через ssw, необходимо иметь доступ до http терминала сервера.
При установке пакета ecss-restfs необходимо указать следующие ответы:
- На вопрос "Необходимо ли настроить телефонную книгу?" ответить положительно ("Да");
- Далее в соответствии с сервисом/сервисами которые будут использоваться для формировании адресной книги заполнить параметры доступа; Список вопросов при инсталляции пакетов приведен в разделе "Инсталляция системы".
Если на момент настройки сервиса пакет ecss-restfs уже был установлен, используйте команду переконфигурирования сервиса:
$ sudo dpkg-reconfigure ecss-restfs
Сервис можно временно сконфигурировать и через файл /usr/lib/ecss/ecss-restfs/conf/address-book/card-settings.json.
Пример конфигурационного файла:
{
"ldap": {
"base_name": "cn=admin,dc=eltex,dc=com",
"password": "",
"domain": "ou=users,dc=eltex,dc=com",
"server": "localhost",
"attrs": [
"mail",
"telephoneNumber",
"displayName"
],
"translit": "false",
"scope": "subtree"
},
"ssw": {
"protocol": "https",
"server": "localhost:9999",
"user": "admin",
"password": "password",
"domain": "biysk.local",
"translit": "false",
"limit": "10000"
},
"mysql": {
"server": "address-book.mysql.ecss",
"port": "3306",
"user": "address_book",
"password": "address_book",
"db": "ecss_address_book",
"domain": "biysk.local",
"procedure": "getContactBook",
"limit": "10000",
"translit": "false",
"offset": "0"
},
"carddav": {
"backend": "ECSS-Restfs-vcard",
"displayname": "",
"protocol": "http",
"server": "localhost",
"port": "9990",
"args": "",
"description": "Address book ECSS"
},
"global": {}
}
Изменив параметры в файле необходимо перезагрузить сервис ecss-restfs.
$ sudo systemctl restart ecss-restfs
Однако настройки, выставленные в этом файле будут сброшены после обновления пакета ecss-restfs. Верная схема настройки сервиса через установку или реконфигурирование пакета ecss-restfs.
Шаблоны
Шаблоны для формирования адресных книг для телефонов различных производителей должны находится по пути /etc/ecss/ecss-restfs/template.
Имя каждого шаблона должно соответствовать следующему виду: -<tempate_name>.xml, где <tempate_name> — имя шаблона.
В текущей версии в данном каталоге уже имеются готовые шаблоны для ТА Cisco, GrandStream, стандартный шаблон common.xml(подойдет для ТА Yealink, Eltex VP). Также есть шаблон для выгрузки книги в формате vcard(используют мобильные приложения).
Шаблон common.xml
<{{context.vendor}}IPPhoneDirectory>
<Title>Restfs address book</Title>
<Prompt>Prompt text.</Prompt>
{% for id, person in ipairs(context.data) do %}
<DirectoryEntry>
<Name>{{string.strip(trim(person.name), context.param.name_len)}}</Name>
{% for tag, val in pairs(person.phone) do %}
<Telephone>{{trim(val)}}</Telephone>
{% end %}
</DirectoryEntry>
{% end %}
</{{context.vendor}}IPPhoneDirectory>
Шаблон grandstream.xml
<?xml version="1.0" encoding="UTF-8"?>
<AddressBook>
<version>1</version>
{% for id, person in ipairs(context.data) do %}
<Contact>
<FirstName searchName="{{person.name}}">{{person.name}}</FirstName>
<MiddleName searchName="{{person.middle_name}}">{{person.middle_name}}</MiddleName>
<LastName searchName="{{person.last_name}}">{{person.last_name}}</LastName>
<!-- phone -->
{% for tag, val in pairs(person.phone) do %}
<Phone>
<phonenumber>{{val}}</phonenumber>
<accountindex>{{id}}</accountindex>
</Phone>
{% end %}
<!-- phone end -->
<Group>0</Group>
<PhotoUrl/>
<RingtoneUrl>./</RingtoneUrl>
<RingtoneIndex>0</RingtoneIndex>
<!-- mail -->
{% for _, val in ipairs(person.email) do %}
<Mail>{{val}}</Mail>
{% end %}
<!-- mail end -->
</Contact>
{% end %}
</AddressBook>
Шаблон vcard.vcf
{% for id, person in ipairs(context.data) do %}
BEGIN:VCARD
VERSION:4.0
PRODID:-//ECSS RESTFS//Carddav 3.11//EN
UID:{{ ngx.md5(person.name .. id):gsub("%a", "") }}
CATEGORIES: {{person.domain}}
FN:{*person.name*}
N:{*person.last_name*};{*person.first_name*};{*person.middle_name*};;
{% for _, val in ipairs(person.email) do %}
EMAIL;TYPE=INTERNET:{*val*}
{% end %}
{% for tag, val in pairs(person.phone) do %}
TEL;TYPE=WORK:{*val*}
{% end %}
REV:{{ ngx.localtime() }}
END:VCARD
{% end %}
На основе данных примеров можно создавать пользовательские шаблоны для ТА или приложений разных вендоров. Структура файла для загрузки адресной книги как правило приводится в документации к ТА.
Чтобы телефон мог воспользоваться заданным шаблоном, необходимо, чтобы в запросе присутствовал параметр user_agent=<tempate_name>, например:
http://192.168.1.21:9990/mysql?host=book&user_agent=grandstream
Синтаксис и параметры запроса приведены в таблице 1.
Если шаблон не обнаружен, то возвращается адресная книга по стандартному шаблону.
Использование сервиса
Общая схема запроса
Для получения адресной книги запрос должен соответствовать следующему синтаксису:
Таблица 1
Синтаксис запроса |
---|
CODE
|
Параметры: |
|
Если информация по запросу существует, возвращается код 200, а в теле ответа - телефонная книга. При возникновении ошибки причину можно посмотреть в файлах /var/log/ecss/restfs/error-card-*.log.
Пример:
Запрос:
curl 'http://192.168.1.21:9990/mysql?host=book&domain=biysk.local' -v
Ответ:
* Trying 192.168.1.21:9990...
* TCP_NODELAY set
* Connected to 192.168.1.21 (192.168.1.21) port 9990 (#0)
> GET /mysql?host=book&domain=biysk.local HTTP/1.1
> Host: 192.168.1.21:9990
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.14.0 (Ubuntu)
< Date: Thu, 26 Aug 2021 04:34:04 GMT
< Content-Type: text/xml; charset=utf-8
< Content-Length: 33944
< Connection: keep-alive
< X-Backend: MYSQL
< X-Cache-Status: MISS
< Backend: book
<
<Curl/7.68.0IPPhoneDirectory>
<Title>Restfs address book</Title>
<Prompt>Prompt text.</Prompt>
<DirectoryEntry>
<Name></Name>
<Telephone>240001</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>remote office</Name>
<Telephone>240006</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name></Name>
<Telephone>240007</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Svetlana</Name>
<Telephone>240100</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Aleksandr</Name>
<Telephone>240101</Telephone>
</DirectoryEntry>
...
</Curl/7.68.0IPPhoneDirectory>
* Connection #0 to host 192.168.1.21 left intact
Пример ошибки запроса к отутствующему домену:
sasha@bsk2:~$ curl 'http://192.168.1.21:9990/error?host=book&domain=biysk&limit=3' <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.14.0 (Ubuntu)</center> </body> </html>
Пример ошибки когда сервис не настроен, например LDAP:
sasha@bsk2:~$ curl 'http://192.168.1.21:9990/ldap?host=book&domain=biysk&limit=3' <html> <head><title>500 Internal Server Error</title></head> <body bgcolor="white"> <center><h1>500 Internal Server Error</h1></center> <hr><center>nginx/1.14.0 (Ubuntu)</center> </body> </html>
В логе причина - "Can't contact LDAP server":
sasha@ecss1:/var/log/ecss/restfs$ cat error-card-ldap.log 2021/08/27 14:27:17 [error] 5907#5907: *14124 lua entry thread aborted: runtime error: /usr/lib/ecss/ecss-restfs/lua/card-ldap.lua:84: Can't contact LDAP server stack traceback: coroutine 0: [C]: in function 'assert' /usr/lib/ecss/ecss-restfs/lua/card-ldap.lua:84: in function </usr/lib/ecss/ecss-restfs/lua/card-ldap.lua:1>, client: 127.0.0.1, server: ecss-restfs-card-backend, request: "GET /ldap?host=book&domain=biysk&limit=3 HTTP/1.0", host: "127.61.0.1:9991"
Примеры запросов адресной книги
Запрос по общему шаблону:
sasha@bsk2:~$ curl 'http://192.168.1.21:9990/mysql?host=book&domain=biysk.local&user_agent=yealink&skip_no_disp=true&translit=false&limit=5'
<YealinkIPPhoneDirectory>
<Title>Restfs address book</Title>
<Prompt>Prompt text.</Prompt>
<DirectoryEntry>
<Name>remote office</Name>
<Telephone>240006</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Светлана</Name>
<Telephone>240100</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Александр</Name>
<Telephone>240101</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>GPON</Name>
<Telephone>240462</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Электрики</Name>
<Telephone>240464</Telephone>
</DirectoryEntry>
</YealinkIPPhoneDirectory>
Пример запроса по шаблону для ТА GrandStream:
sasha@bsk2:~$ curl 'http://192.168.1.21:9990/mysql?host=book&domain=biysk.local&user_agent=grandstream&skip_no_disp=true&translit=false&limit=3'
<?xml version="1.0" encoding="UTF-8"?>
<AddressBook>
<version>1</version>
<Contact>
<FirstName searchName="remote office">remote office</FirstName>
<MiddleName searchName="undefined">undefined</MiddleName>
<LastName searchName="undefined">undefined</LastName>
<!-- phone -->
<Phone>
<phonenumber>240006</phonenumber>
<accountindex>1</accountindex>
</Phone>
<!-- phone end -->
<Group>0</Group>
<PhotoUrl/>
<RingtoneUrl>./</RingtoneUrl>
<RingtoneIndex>0</RingtoneIndex>
<!-- mail -->
<!-- mail end -->
</Contact>
<Contact>
<FirstName searchName="Светлана">Светлана</FirstName>
<MiddleName searchName=""></MiddleName>
<LastName searchName=""></LastName>
<!-- phone -->
<Phone>
<phonenumber>240100</phonenumber>
<accountindex>2</accountindex>
</Phone>
<!-- phone end -->
<Group>0</Group>
<PhotoUrl/>
<RingtoneUrl>./</RingtoneUrl>
<RingtoneIndex>0</RingtoneIndex>
<!-- mail -->
<Mail>sv@email.loc</Mail>
<!-- mail end -->
</Contact>
<Contact>
<FirstName searchName="Александр">Александр</FirstName>
<MiddleName searchName="middle">middle</MiddleName>
<LastName searchName="last">last</LastName>
<!-- phone -->
<Phone>
<phonenumber>240101</phonenumber>
<accountindex>3</accountindex>
</Phone>
<!-- phone end -->
<Group>0</Group>
<PhotoUrl/>
<RingtoneUrl>./</RingtoneUrl>
<RingtoneIndex>0</RingtoneIndex>
<!-- mail -->
<Mail>asz@email.loc</Mail>
<Mail>asz@sibnet.ru</Mail>
<!-- mail end -->
</Contact>
</AddressBook>
Пример запроса по протоколу CardDAV(при запросе из браузера предлагает сохранить файл контактов - vcard.vcf)
sasha@bsk2:~$ curl 'http://192.168.1.21:9990/mysql?host=book&domain=biysk.local&user_agent=vcard&skip_no_disp=true&translit=false&limit=3'
BEGIN:VCARD
VERSION:4.0
PRODID:-//ECSS RESTFS//Carddav 3.11//EN
UID:834057494898241694630
CATEGORIES: biysk.local
FN:remote office
N:undefined;undefined;undefined;;
TEL;TYPE=WORK:240006
REV:2021-08-27 13:52:00
END:VCARD
BEGIN:VCARD
VERSION:4.0
PRODID:-//ECSS RESTFS//Carddav 3.11//EN
UID:5607334834221462834727
CATEGORIES: biysk.local
FN:Светлана
N:;;;;
EMAIL;TYPE=INTERNET:sv@email.loc
TEL;TYPE=WORK:240100
REV:2021-08-27 13:52:00
END:VCARD
BEGIN:VCARD
VERSION:4.0
PRODID:-//ECSS RESTFS//Carddav 3.11//EN
UID:6500235108102668882
CATEGORIES: biysk.local
FN:Александр
N:last;first;middle;;
EMAIL;TYPE=INTERNET:asz@email.loc
EMAIL;TYPE=INTERNET:asz@sibnet.ru
TEL;TYPE=WORK:240101
REV:2021-08-27 13:52:00
END:VCARD
Сброс кэша для сервиса телефонной книги
Сброс предназначен для принудительного обновления кэша сервиса телефонной книги. При этом происходит внеочередное обращение к БД соответствующего сервиса с целью актуализации кэша. По умолчанию обновление кэша происходит раз в час.
http://<IP>:9990/update/<service>?host=book
- <IP> — ip-адреса сервера, где установлен пакет ecss-restfs;
- <service> — сервис используемый для получения телефонной книги (mysql/ldap/ssw).
Синхронизация телефонной книги SIP-телефонов
Для синхронизации адресной книги с телефоном, нужно в соответствующем меню ввести http адрес запроса, который будет отправляться на SSW.
Общая схема запроса приведена выше в Таблице 1.
На телефонном аппарате в параметрах настройки удаленной телефонной книги нужно указать URL доступа к сервису с необходимыми параметрами.
Пример для ТА Yealink:
Пример для ТА Eltex VP-15:
Подробнее о загрузке и синхронизации адресной книги - в документации по конкретной модели IP телефона.