Pull to refresh

Альтернативный алгоритм очереди в Asterisk

Доброго времени суток!

Работая со звездочкой достаточно продолжительное время, мне периодически приходится решать тривиальную задачу: организовать вариант очереди входящих звонков в call-центре, который по максимуму задействует имеющиеся ресурсы (операторов, линии и т.д.).

Вроде все просто: настраиваешь queues и раскидываешь по операторам, но…понаблюдав за работой этой схемы я заметил одну не очевидную с первого взгляда вещь – пока не будет обработан первый входящий звонок в очереди, остальные клиенты этой очереди будут просто висеть и не попадать на свободных операторов (см. схему). А операторы, как известно, тоже люди…и без должного контроля очень даже ленивые!

Схема работы queue в Asterisk
image

Поразмыслив над задачей, я решил полностью отказаться от queue и сделать все на dial-ах.

Алгоритм написан на ael-ке и реализует стратегию обзвона linear, хотя никто не мешает переделать его под фактически любую из queues.conf:

context from-in {

_X. => {
	Set(dialnum=10,20,30,40); // внутренние номера наших операторов
        y=3;    //количество повторов прохождения по операторам 
        array:   // метка для возврата
        while (${y} > 0) {    // запускаем первый цикл
                x=1;  // задаем первый элемент массива номеров операторов
                z=1; // инициируем переменную, чтобы запустить цикл перебора номеров
                while (${z} > 0) { //запускаем цикл перебора номеров в переменной dialnum
                        nextstep:  //метка для возврата
                        z=0; // обнуляем переменную 
                        Set(num=${CUT(dialnum,\,,${x})});    //вытягиваем из переменной dialnum значение номера оператора
                        z=LEN(${num});   // вычисляем длину значения переменной
                        NoOp(-----------------${num}--------------);
                        if (${z} = 0) {  //если номера закончились, то 
                                y=${y}-1;    //уменьшить значение количества повторов
                                Wait(3);   //вставляем паузу пока все операторы заняты (на самом деле сюда можно запихать например Playback с какой нибудь фразой, типа "все операторы заняты ожидайте" и проиграть короткий ролик с рекламой)
                                goto array;  //и повторяем прозвон операторов
                        } else {  //вытащили значение номера оператора
                                Set(devstat=${DEVICE_STATE(SIP/${num})});   //присваиваем переменной devsat значение статуса оператора
                                switch (${devstat}) {     //проверяем статус оператора
                                        case NOT_INUSE:    //если он не занят, то
                                                x=${x}+1;   //увеличиваем значение для выборки по следующему номеру оператора из списка в случае если данный оператор не возьмет трубку
                                                Dial(SIP/${num},10,trg);    //вызываем оператора
                                                goto nextstep;  //если он ен взял трубку - переходим к следующему
                                        default:     //если оператор занят, не в сети или вызывается, то 
                                                x=${x}+1; // переходим к следующему оператору
                                                NooP(--------device is ${devstat}---------);
                                                goto nextstep;
                                };
                        };
                };
                NoOp(------------ARRAY FINISH------------);
        };
        Hangup();
};
};


Как вариант, задействовать базу данных в том случае, если наши операторы не статические, а постоянно меняются или добавляются. Для этого создаем таблицу, например, такую:

create table operators (`extension` int(12) NOT NULL default '', `numbers` varchar(255) NOT NULL default '');


И вместо:

Set(dialnum=10,20,30,40);


Прописываем:

Set(dialnum=${ODBC_DIALNUM(${EXTEN})});     //делает выборку из таблицы в БД по соответствующему полю


Открываем func-odbc.conf и добавляем:

[DIALNUM]
readsql=SELECT numbers FROM operators WHERE EXTENSION LIKE '%${SQL_ESC(${ARG1})}%'


Рассказывать как подключается odbc и что это такое здесь не буду — есть куча замечательной документации в интернетах!

Добавляем в табличку несколько направлений с соответствующими операторами:

extension numbers
222222 10,20,30
333333 10,20,40
444444 30,20,40


И теперь при звонке на определенный номер будут вызываться нужные операторы.
Прикрутить сюда musiconhold, announce можно точно также как это делается в queues.conf.

Спасибо за внимание и конструктивную критику!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.