Asterisk™: будущее телефонии Второе издание - Меггелен Джим Ван
Шрифт:
Интервал:
Закладка:
read=SELECT pin,status FROM ast_hotdesk WHERE extension = '${E}' с помощью функции ARRAY() можно в одном обращении к базе данных сохранять каждый столбец данных строки в собственной переменной:
exten => _110[1-5],n,Set(ARRAY(${E}_PIN,${E}_STATUS)=${HOTDES K_INFO(${E})})
После выполнения SQL-запроса возвращенное значение (если таковое имеется) присваивается переменной канала RETURNED_VALUE (возвращенное значение).
Итак, в первых двух строках следующего фрагмента кода мы передаем значение status и значение, содержащееся в переменной ${E} (например, 1101) в функцию HOTDESK_INFO(). Затем эти два значения замещаются в SQL-запросе на ${ARG1} и ${ARG2} соответственно, SQL-запрос выполняется, а возвращенное значение присваивается переменной канала ${E}_STATUS.
Итак, теперь закончим шаблонный добавочный номер:
exten => _110[1-5],n,Set(${E}_STATUS=${HOTDESK_INFO(status,${E})}) exten => _110[1-5],n,Set(${E}_PIN=${HOTDESK_INFO(pin,${E})}) exten => _110[1-5],n,GotoIf($[${ISNULL(${${E}_STATUS})}]?invalid_user,1) ; check if ${E}_STATUS is NULL
exten => _110[1-5],n,GotoIf($[${${E}_STATUS} = 1]?logout,1:login,1) Присвоив значение столбца status переменной ${E}_STATUS (если был набран добавочный номер 1101, имя переменной было бы 1101_STATUS), проверяем, было ли возвращено значение из базы данных (контроль ошибок). Для этой проверки используем функцию ISNULL(). Последняя строка фрагмента кода проверяет статус телефона, и, если в текущий момент он зарегистрирован, будет выполнен его выход из системы. Если он еще не зарегистрирован, управление перейдет к добавочному номеру login c приоритетом 1 в рамках того же контекста[117].
В следующей после 1.4 версии (в настоящее время готовящейся к выпуску) с выражениями, выполняемыми readsql, можно будет использовать переменную канала ${0DBCR0WS}. GotoIf() можно заменить примерно следующим:
exten => _110[1-5],n,GotoIf($[${0DBCR0WS} < 0]?invalid_user,1)
Добавочный номер login выполняет несколько начальных проверок, чтобы убедиться в достоверности введенного агентом кода. Мы предоставляем три попытки для ввода правильного пин-кода. Если все три ввода недействительны, вызов направляется на добавочный номер login_fail (неудачная регистрация) (который будет написан позже).
exten => login,1,No0p() ; задаем исходное значение счетчика
exten => login,n,Set(PIN_TRIES=0) ; задаем максимальное число попыток регистрации
exten => login,n,Set(MAX_PIN_TRIES=3)
exten => login,n(get_pin),No0p() ; увеличиваем счетчик попыток ввода пин-кода exten => login,n,Set(PIN_TRIES=$[${PIN_TRIES} + 1]) exten => login,n,Read(PIN_ENTERED|enter-password|${LEN(${${E}_PIN})}) exten => login,n,GotoIf($[${PIN_ENTERED} = ${${E}_PIN}]?valid_login,1) exten => login,n,Playback(invalid-pin)
exten => login,n,GotoIf($[${PIN_TRIES} <=${MAX_PIN_TRIES}]?get_pin:login_fail,1) Если введен соответствующий пин-код, проверяем регистрационное имя с помощью добавочного номера valid_login (действительное регистрационное имя). Сначала используем переменную CHANNEL (канал), чтобы выяснить, с какого телефона выполняется звонок. Обычно значение переменной имеет примерно такой вид: SIP/desk_1-ab4034c. Поэтому с помощью функции CUT() сначала отбрасываем часть строки SIP/, а оставшееся значение присваиваем переменной L0CATI0N (местоположение). Затем убираем часть строки -ab4034c, а оставшуюся строку, desk_1, присваиваем переменной L0CATI0N. exten => valid_login,1,No0p()
; отбрасываем технологию канала, а оставшуюся строку сохраняем в переменной ; L0CATI0N
exten => valid_login,n,Set(L0CATI0N=${CUT(CHANNEL,/,2)}) ; отбрасываем уникальный идентификатор и сохраняем оставшуюся строку
; в переменной 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}'