и сохраняем оставшуюся строку
; в переменной LOCATION
exten => valid_login,n,Set(LOCATION=${CUT(LOCATION,-,1)}) Используем еще одну специальную функцию HOTDESK_CHECK_PHONE_ LOGINS(), созданную в файле func_odbc.conf, для проверки, не зарегистрирован ли по этому телефону какой-то другой пользователь. Если количество ранее зарегистрированных пользователей больше 0 (их не может быть больше 1, но мы все равно проводим проверку и сброс для всех вариантов), функция выполняет логику добавочного номера logout_login (отмена регистрации регистрационного имени). Если никто из агентов не был зарегистрирован ранее, обновляем статус регистрации для этого пользователя с помощью функции HOTDESK_ STATUS():
exten => valid_login,n,Set(ARRAY(USERS_LOGGED_IN)=${HOTDESK_CHECK_PHONE_ LOGINS (${LOCATION})})
exten => valid_login,n,GotoIf($[${USERS_LOGGED_IN} > 0]?logout_login,1) exten => valid_login,n (set_login_status),NoOp()
Задаем для телефона статус '1' - здесь и происходит регистрация ПРИМЕЧАНИЕ: здесь надо экранировать запятую, потому что в приложении Set() есть аргументы
exten => valid_login,n,Set(HOTDESK_STATUS(${E})=1,${LOCATION}) exten => valid_login,n,GotoIf ($[${ODBCROWS} < 1]?error,1) exten => valid_login,n,Playback(agent-loginok) exten => valid_login,n,Hangup()
Создаем в файле func_odbc.conf функцию для записи следующим образом:
[STATUS]
prefix=HOTDESK
dsn=asterisk
write=UPDATE ast_hotdesk SET status = '${VAL1}', location = '${VAL2}' WHERE extension = '${ARG1}'
Ее синтаксис очень похож на синтаксис read, обсуждаемый ранее в данной главе, но есть несколько новшеств, поэтому рассмотрим их, прежде чем двигаться дальше.
Первое, на что вы, возможно, обратили внимание, - теперь в SQL-запросе есть переменные и ${VALx}, и ${ARGx}. Они содержат значения, передаваемые нами в функцию из диалплана. В данном случае имеется две переменных VAL и одна переменная ARG, которые были заданы из диалплана посредством такого выражения: Set(HOTDESK_STATUS(${E})=1,${LOCATION})
Поскольку приложение диалплана Set () может также принимать аргументы (можно задавать множество переменных и значений, разделяя их запятыми или символами вертикальной черты), необходимо экранировать запятую обратным слэшем (), чтобы синтаксический анализатор выражения обрабатывал ее как часть не приложения Set (), а функции HOTDESK_STATUS().
Обратите внимание, что данный синтаксис немного отличается от синтаксиса функции для чтения. Это говорит Asterisk о том, что необходимо выполнять запись (тот же синтаксис, что и в других функциях диа- лплана).
Значение переменной ${E} передается в функцию H0TDESK_STATUS(), возвращаемое значение которой затем будет доступно в SQL-выражении в файле func_odbc.conf как переменная ${ARG1}. После этого передаем два значения: 1 и ${L0CATI0N}. Они доступны SQL-запросу в переменных ${VAL1} и ${VAL2} соответственно.
Как упоминалось ранее, если бы перед тем, как зарегистрироваться в системе, нам пришлось отменить регистрацию одного или более агентов, мы бы реализовывали это с помощью добавочного номера logout_ login. В данном фрагменте диалплана для перебора всех строк базы данных и внесения необходимых изменений будет использоваться приложение While(). Скорее всего, цикл будет выполнен только один раз, но это хороший пример того, как можно обновлять или проводить синтаксический разбор множества строк базы данных: exten => logout_login,1,No0p()
; для всех пользователей, зарегистрированных для данного устройства, задать
; статус 'незарегистрирован'
exten => logout_login,n,Set(R0W_C0UNTER=0)
exten => logout_login,n,While($[${R0W_C0UNTER} < ${USERS_L0GGED_IN}]) Переменная ${USERS_L0GGED_IN} была задана ранее функцией H0TDESK_ CHECK_PH0NE_L0G INS(), которая присвоила ей значение 1 или больше. Мы сделали это, подсчитав количество измененных строк:
; func_odbc.conf [CHECK_PH0NE_L0GINS] prefix=H0TDESK dsn=asterisk
read=SELECT C0UNT(status) FR0M ast_hotdesk WHERE status = '1' AND location = '${ARG1}'
Затем с помощью функции H0TDESK_L0GGED_IN_USER() получаем добавочный номер зарегистрированного пользователя. Переменная L0CATI0N содержит значение desk_1, обозначающее устройство, которое мы хотим проверить, а ${R0W_C0UNTER} содержит номер итерации цикла. Оба эти значения передаются как аргументы функции диалплана. Результат затем присваивается переменной WH0 (кто):
exten => logout_login,n,Set(WH0=${H0TDESK_L0GGED_IN_USER(${L0CATI0N}, ${R0W_C0UNTER})})
Далее функция H0TDESK_L0GGED_IN_USER() извлекает из базы данных строку, соответствующую итерации цикла, которую мы пытаемся обработать:
[L0GGED_IN_USER]
prefix=H0TDESK
dsn=asterisk
read=SELECT extension FR0M ast_hotdesk WHERE status = '1' AND location = '${ARG1}' 0RDER BY id LIMIT '1' 0FFSET '${ARG2}'
Теперь, когда известен добавочный номер, данные для которого требуется изменить, выполняем запись в функцию HOTDESK_STATUS() и присваиваем 0 столбцу status для строки, в которой добавочный номер соответствует значению переменной ${WHO} (то есть 1101). Завершаем цикл с помощью EndWhile() и возвращаемся к добавочному номеру valid_login в приоритет с меткой set_login_status (как обсуждалось ранее):
exten => logout_login,n,Set(HOTDESK_STATUS(${WHO})=0) ; отмена регистрации телефона
exten => logout_login,n,Set(ROW_COUNTER=$[${ROW_COUNTER} + 1]) exten => logout_login,n,EndWhile()
exten => logout_login,n,Goto(valid_login,set_login_status) ; возвращаемся к процессу регистрации
Все остальное должно быть достаточно понятным (если что-то неясно, вернитесь к главам 5 и 6). Затруднения может вызвать только прием с использованием переменной канала ${ODB CROWS}, которая задается функцией HOTDESK_STATUS(). Она сообщает, сколько строк было изменено в результате SQL- запроса UPDATE (обновить). Мы предполагаем, что это значение равно 1. Если значение ${ODBCROWS} меньше 1, мы рассматриваем это как ошибку и обрабатываем соответствующим образом: exten => logout,1,NoOp()
exten => logout,n,Set(HOTDESK_STATUS(${E})=0) exten => logout,n,GotoIf($[${ODBCROWS} < 1]?error,1) exten => logout,n,Playback(silence/1&agent-loggedoff) exten => logout,n,Hangup()
exten => login_fail,1,NoOp()
exten => login_fail,n,Playback(silence/1&login-fail) exten => login_fail,n,Hangup()
exten => error,1,NoOp()
exten => error,n,Playback(silence/1&connection-failed) exten => error,n,Hangup()
exten => invalid_user,1,NoOp()
exten => invalid_user,n,Verbose(1|Hot Desk extension ${E} does not exist)
exten => invalid_user,n,Playback(silence/2&invalid)
exten => invalid_user,n,Hangup()
Также включаем контекст hotdesk_outbound, который будет обрабатывать наши исходящие звонки после регистрации агента в системе:
include => hotdesk_outbound Контекст hotdesk_outbound преимущественно следует тем же принципам и правилам, которые обсуждались ранее, поэтому не будем рассматривать его слишком подробно. Фактически контекст [hotdesk_ outbound] будет обрабатывать все номера, набираемые с настольных телефонов. Сначала задаем переменную LOCATION, используя переменную CHANNEL, затем определяем,