Как стать автором
Обновить

Динамические очереди звонков в Asterisk

Время на прочтение 5 мин
Количество просмотров 20K
Добрый день уважаемые читатели сего сайта.
Сегодня я хотел бы рассказать может быть о странном способе управления очередями в asterisk.
Итак.

Дано:
1. сервер asterisk1.8.32.3
2. sip клиенты(35 номеров). Нумерация двухзначная. Первый номер 11, последний 46.
3. Очереди звонков. При поступлении звонка на городской номер, проговаривается меню и предлагается нажать на цифры от 1 до 4. при нажатии звонок перебрасывается в очередь 1,2,3 или 4 соответственно.

Как выглядит файл queues.conf сейчас:
[queue-1]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0
member => SIP/24
member => SIP/25
member => SIP/17
member => SIP/23
member => SIP/21
member => SIP/18

[queue-2]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0
member => SIP/18
member => SIP/21
member => SIP/23

[queue-3]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0
member => SIP/37
member => SIP/35
member => SIP/31
member => SIP/33
member => SIP/34
member => SIP/32

[queue-4]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0
member => SIP/24
member => SIP/25
member => SIP/37
member => SIP/18
member => SIP/32

То есть мы видим, что файл очередей задан статически. Номера добавляются/удаляются руками и после каждого изменения файла надо делать queue reload all. То есть надо зайти на сервер asterisk в консоль скажем, затем asterisk -vvvvvvvvvvvr и набрать эту команду.

Задача:

Сделать так, чтобы members добавлялись в очередь динамически. И состав очереди определялся бы содержимым соответствующей таблицы в mysql.
То есть. Состав очереди определяется mysql.
Соответственно данные в таблицу mysql могут вноситься как через консоль mysql так и через любую другую программу доступа к мускулю. Я например написал свою «программу» используя LAMP для чтения и изменения соответствующей таблицы с очередями.

Решение:

1. Создаем таблицу в какой нибудь базе mysql. Я не буду описывать процесс создания таблицы, просто приведу пример моей рабочей таблицы.
mysql> desc queue;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| priznak | int(1) | YES | | NULL | |
| queue | varchar(100) | YES | | NULL | |
| sip | varchar(100) | YES | | NULL | |
| sort_queue | int(2) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+

и данные самой таблицы:
mysql> select * from queue;
+----+---------+---------+--------+------------+
| id | priznak | queue | sip | sort_queue |
+----+---------+---------+--------+------------+
| 1 | 1 | queue-1 | SIP/24 | 4 |
| 2 | 1 | queue-1 | SIP/17 | 2 |
| 3 | 1 | queue-1 | SIP/23 | 3 |
| 4 | 0 | queue-1 | SIP/21 | 4 |
| 5 | 1 | queue-1 | SIP/25 | 1 |
| 6 | 1 | queue-1 | SIP/18 | 6 |
| 7 | 1 | queue-2 | SIP/18 | 1 |
| 8 | 0 | queue-2 | SIP/21 | 2 |
| 9 | 1 | queue-2 | SIP/23 | 2 |
| 10 | 1 | queue-3 | SIP/37 | 1 |
| 11 | 1 | queue-3 | SIP/35 | 2 |
| 12 | 1 | queue-3 | SIP/31 | 3 |
| 13 | 1 | queue-3 | SIP/33 | 4 |
| 14 | 1 | queue-3 | SIP/34 | 5 |

поясню поля таблицы.
Id — ключ.
Priznak — 0/1. Соответственно если 0, то данный номер не участвует в очереди
queue — название очереди
sip — СИП аккаунт.
sort_queue — порядок в котором SIP аккаунты будут участвовать в обзвоне. Скажем в очереди queue надо, что бы первым звонил номер SIP/25, затем SIP/17 и т. д.

2. Теперь настраиваем сам asterisk для работы с очередями в таком виде.
Хочу предупредить, что здесь я использую план набора написанный на AEL. В основном потому, что синтаксис AEL близок к C++. И циклы на AEL писать гораздо удобнее и они лучше читаются.

Создаем файл extensions.ael
Я не буду писать «конкретику», по поводу того как входящий звонок поступает на asterisk и что с ним дальше происходит, скажу только что при нажатии на кнопку 1,2,3 или 4 вызывается контекст описанный в extensions.ael.

Теперь содержимое самого файла с комментариями:
push-1 => {
// отвечаем на звонок
answer();
// подключаемся к mysql
MYSQL(Connect connid 192.168.1.1 server user passwd);
// в цикле удаляем все membes из очереди. Номера помним с 11 по 46 включительно.
for (x=11;${x}<=46;x=${x}+1) {
// собственно удаление. Команда asterisk'а.
RemoveQueueMember(queue-1,SIP/${x});
};

// далее делаем запрос из таблицы. Мы ищем сколько позиций будет найдено в нашем запросе. Мы ищем сколько members имеют признак «1», то есть участвующие в очереди.
MYSQL(Query resultid ${connid} select count(*) as co from queue where queue='queue-1' and priznak=1 order by sort_queue);
MYSQL(fetch fetchid ${resultid} co);

// может статься так что в очереди в данный момент будет всего один номер. Мы не можем знать заранее сколько номеров будет в очереди и процесс выборки астериском данных из таблицы будет разным. То есть если найдено одно совпадение то выборка будет описана так, а если несколько то по другому. Поэтому мы проверяем сколько совпадений найдено.
// если совпадений больше чем одно, то делаем запрос(нам нужно поле sip) с признаком «1» и сортировкой по полю «sort_queue».
if (${co}>1) {

MYSQL(Query resultid ${connid} select sip from queue where queue='queue-1' and priznak=1 order by sort_queue);
MYSQL(fetch fetchid ${resultid} sip);
// добавляем первый найденный номер командой AddQueueMember.

// для общего развития. Если найденных значений в таблица больше чем одно, то сначала что то делаем с первым (MYSQL(fetch fetchid ${resultid} sip);), а потом все остальные в цикле (MYSQL(NextResult resultid ${connid});
MYSQL(fetch fetchid ${resultid} sip_next);)

AddQueueMember(queue-1,${sip});

// затем в цикле делаем поиск остальных результатов и соответственно добавляем их в очередь командой AddQueueMember
for (x=1;${x}<${co};x=${x}+1) {

MYSQL(NextResult resultid ${connid});
MYSQL(fetch fetchid ${resultid} sip_next);
AddQueueMember(queue-1,${sip_next});
};
}
// если результат одна штука, тогда делаем запрос и добавляем найденный номер в очередь командой AddQueueMember(queue-1,${sip});
else {

MYSQL(Query resultid ${connid} select sip from queue where queue='queue-1' order by sort_queue);
MYSQL(fetch fetchid ${resultid} sip);
AddQueueMember(queue-1,${sip});
};

// затем очищаем результат запроса и разъединяемся.
MYSQL(Clear ${resultid});
MYSQL(Disconnect ${connid});

// собственно здесь мы запускаем очередь.
queue(queue-1,Ct,,,300);
};

Мы вносим изменения в таблицу и АТС при следующем вызове очереди считает те номера которые надо. Скажем что бы какой то номер не участвовал в обзвоне надо поставить ему признак «0».

Для других очередей все тоже самое, только меняется название очереди.

Вроде все.

Сразу хочу сказать, что цикл удаления/добавления отрабатывается за 1-2 секунды, что в моем случае нормально(задержек нет)

Также я пробовал работать с очередями с помощью extconfig.conf. В этом файле описывается то, с чем мы можем работать через mysql. То есть все параметры очереди будут не в файле, а в mysql. Лично для меня файл читать гораздо проще и легче, поэтому этот вариант я не использовал.

Теперь файл queues.conf выглядит вот так:
[queue-1]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0

[queue-2]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0

[queue-3]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0

[queue-4]
music = default
strategy=linear
timeout=10
wrapuptime=0
ringinuse=yes
periodic-announce-frequency = 30
joinempty=no
leavewhenempty=no
announce-position=no
announce-holdtime=no
announce-frequency=0
Все настройки самой очереди хранятся в файле, а members добавляются динамически.

На этом все. Спасибо.
Теги:
Хабы:
+1
Комментарии 11
Комментарии Комментарии 11

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн