Каждый день клиенты ставят задачи, для решения которых нужно придумать что-то новое, изучить или написать. Постараюсь иногда рассказывать о тех, которых можно рассказать понятным образом.
На этот раз простая задача — для группы секретарей (a'la простейший call-центр) сделать механизм входа/выхода оператора и отображение текущего статуса на телефоне. Так как это секретари, то они иногда уходят, относят бумаги и оголяют тыл на телефонном фронте. Отсюда требования и особенности реализации:
- chan_agent не используется из-за наличия дополнительных обязанностей операторов
- Телефоны имеют возможность отбить вызов, чтобы тот продолжил распределяться в очереди (телефоны Yealink)
- Одна из BLF клавиш настроена на отображение статуса секретаря в очереди. Зеленый — принимает вызовы, красный — нет.
В примере 100 — номер используемый для входа в очередь, 101-103 — номера SIP телефонов секретарей. Под конкретную ситуацию пример можно обобщить или дописать по желанию.
Экстенжен для организации очереди:
exten => 100,1,Queue (100,t,,,90)
exten => 100,n,Playback (custom/bye_dnd)
exten => 100,n,Hangup ()
Экстенжен, выполняющий добавление/удаление секретаря из очереди при нажатии BLF клавиши на телефоне, использует контекст sub-queue-member, описанный ниже:
exten => _100*XXX,1,GoSub (sub-queue-member,s,1 (${EXTEN:4}))
Прописываем hint экстенжены, чтобы отображать корректный статус секретаря используя BLF клавишу:
exten => 100*101,hint,Custom:QueueStat101
exten => 100*102,hint,Custom:QueueStat102
exten => 100*103,hint,Custom:QueueStat102
Функция, выполняющая несколько функций при нажатии BLF клавиши:
- Добавление/удаление телефона из очереди
- Обновление Custom статуса
При вызове функции считывается текущий список устройств, зарегистрированных в очереди, если запрошенный внутренний номер уже находится в очереди — происходит удаление, если нет — добавление нового участника очереди (устройство не должно быть прописано в очереди статически в queues.conf) и соответственно обновляется статус.
[sub-queue-member]
exten => s,1,Set (LIST=${QUEUE_MEMBER_LIST (100)})
exten => s,n,Set (X=1)
exten => s,n,Set (DEV=${CUT (LIST,\,,${X})})
exten => s,n,While ($[${EXISTS(${DEV})}])
exten => s,n,Set (DEV=${DEV:4})
exten => s,n,GotoIf ($[${DEV} = ${ARG1}]?del-begin)
exten => s,n,Set (X=$[${X} + 1])
exten => s,n,Set (DEV=${CUT (LIST,\,,${X})})
exten => s,n,EndWhile ()
exten => s,n,Goto (add-begin)exten => s,n (add-begin),GotoIf ($[${ARG1} = 100]?add)
exten => s,n,GotoIf ($[${ARG1} = 101]?add)
exten => s,n,GotoIf ($[${ARG1} = 102]?add)
exten => s,n,Return ()
exten => s,n (add),AddQueueMember (100,SIP/${ARG1})
exten => s,n,Set (DEVICE_STATE (Custom:QueueStat${ARG1})=INUSE)
exten => s,n,Return ()exten => s,n (del-begin),GotoIf ($[${ARG1} = 100]?del)
exten => s,n,GotoIf ($[${ARG1} = 101]?del)
exten => s,n,GotoIf ($[${ARG1} = 102]?del)
exten => s,n,Return ()
exten => s,n (del),RemoveQueueMember (100,SIP/${ARG1})
exten => s,n,Set (DEVICE_STATE (Custom:QueueStat${ARG1})=NOT_INUSE)
exten => s,n,Return ()